Skip to content

Commit

Permalink
migrate wallets
Browse files Browse the repository at this point in the history
  • Loading branch information
0xSulpiride committed Nov 27, 2024
1 parent c8c78b2 commit ee21abb
Show file tree
Hide file tree
Showing 21 changed files with 1,012 additions and 61 deletions.
2 changes: 1 addition & 1 deletion examples/helpers/sdk-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { erc20Abi } from "../../src/sdk/common/abis";

export const generateModularSDKInstance = (privateKey: string, chainId: number, bundlerApiKey: string, index: number = 0) => {
const modularSdk = new ModularSdk(
{ privateKey: privateKey },
privateKey,
{
chainId: chainId,
bundlerProvider: new EtherspotBundler(chainId, bundlerApiKey),
Expand Down
32 changes: 14 additions & 18 deletions src/sdk/base/BaseAccountAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ import { calcPreVerificationGas, GasOverheads } from './calcPreVerificationGas';
import { Factory, Network, NetworkNames, NetworkService, SdkOptions, SignMessageDto, validateDto } from '..';
import { Context } from '../context';
import { PaymasterResponse } from './VerifyingPaymasterAPI';
import { Account, Hex, parseAbi, parseAbiItem, PublicClient, TypedDataParameter, WalletClient } from 'viem';
import { Hex, parseAbi, parseAbiItem, PublicClient, TypedDataParameter } from 'viem';
import { entryPointAbi } from '../common/abis';
import { resolveProperties, Result } from '../common/utils';
import { BaseAccountUserOperationStruct, FeeData, TypedDataField } from '../types/user-operation-types';
import { BigNumber, BigNumberish } from '../types/bignumber';
import { WalletProviderLike, WalletService } from '../wallet';

export interface BaseApiParams {
entryPointAddress: string;
accountAddress?: string;
overheads?: Partial<GasOverheads>;
factoryAddress?: string;
optionsLike?: SdkOptions;
walletClient?: WalletClient;
publicClient?: PublicClient;
account?: Account;
wallet: WalletProviderLike;
}

export interface UserOpResult {
Expand Down Expand Up @@ -54,8 +54,7 @@ export abstract class BaseAccountAPI {
paymasterAPI?: PaymasterAPI;
factoryUsed: Factory;
factoryAddress?: string;
account: Account;
walletClient: WalletClient;
wallet: WalletProviderLike;
publicClient: PublicClient;

/**
Expand All @@ -75,6 +74,12 @@ export abstract class BaseAccountAPI {

this.services = {
networkService: new NetworkService(chainId),
walletService: new WalletService(
params.wallet,
{ provider: rpcProviderUrl},
bundlerProvider.url,
chainId
),
};

this.context = new Context(this.services);
Expand All @@ -84,10 +89,8 @@ export abstract class BaseAccountAPI {
// super();
this.overheads = params.overheads;
this.entryPointAddress = params.entryPointAddress;
this.account = params.account;
this.accountAddress = params.accountAddress;
this.factoryAddress = params.factoryAddress;
this.walletClient = params.walletClient;
this.publicClient = params.publicClient;
}

Expand Down Expand Up @@ -122,11 +125,7 @@ export abstract class BaseAccountAPI {
network: false,
});

return this.walletClient.signMessage(
{
account: this.account,
message: message as Hex
});
return this.services.walletService.signMessage(message as Hex);
}

async setPaymasterApi(paymaster: PaymasterAPI | null) {
Expand Down Expand Up @@ -364,7 +363,6 @@ export abstract class BaseAccountAPI {
const deployerAddress = initCode.substring(0, 42);
const deployerCallData = '0x' + initCode.substring(42);
const estimatedGas = await this.publicClient.estimateGas({
account: this.account,
to: deployerAddress,
data: deployerCallData,
});
Expand Down Expand Up @@ -552,13 +550,11 @@ export abstract class BaseAccountAPI {
}
});

return await this.walletClient.signTypedData({
return await this.services.walletService.signTypedData({
domain,
types: typesObject,
types: typesObject as any,
primaryType: 'UserOperation',
account: this.account,
message
});
//return this.services.walletService.signTypedData(types, message, this.accountAddress);
})
}
}
14 changes: 3 additions & 11 deletions src/sdk/base/EtherspotWalletAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { BaseApiParams, BaseAccountAPI } from './BaseAccountAPI';
import { BootstrapConfig, _makeBootstrapConfig, makeBootstrapConfig } from './Bootstrap';
import { DEFAULT_BOOTSTRAP_ADDRESS, DEFAULT_MULTIPLE_OWNER_ECDSA_VALIDATOR_ADDRESS, Networks, DEFAULT_QUERY_PAGE_SIZE } from '../network/constants';
import { CALL_TYPE, EXEC_TYPE, MODULE_TYPE, getExecuteMode } from '../common';
import { encodeFunctionData, parseAbi, encodeAbiParameters, parseAbiParameters, type WalletClient, type PublicClient, toBytes, concat, getAddress, pad, toHex, isBytes, Account, Hex, isAddress } from 'viem';
import { encodeFunctionData, parseAbi, encodeAbiParameters, parseAbiParameters, concat, getAddress, pad, toHex, isBytes, Hex, isAddress } from 'viem';
import { accountAbi, bootstrapAbi, entryPointAbi, factoryAbi } from '../common/abis';
import { getInstalledModules } from '../common/getInstalledModules';
import { getViemAddress } from '../common/utils/viem-utils';
Expand Down Expand Up @@ -56,11 +56,10 @@ export class EtherspotWalletAPI extends BaseAccountAPI {
this.predefinedAccountAddress = params.predefinedAccountAddress ?? null;
this.bootstrapAddress = Networks[params.optionsLike.chainId]?.contracts?.bootstrap ?? DEFAULT_BOOTSTRAP_ADDRESS;
this.multipleOwnerECDSAValidatorAddress = Networks[params.optionsLike.chainId]?.contracts?.multipleOwnerECDSAValidator ?? DEFAULT_MULTIPLE_OWNER_ECDSA_VALIDATOR_ADDRESS;
this.eoaAddress = this.account.address;
}

getEOAAddress(): Hex {
return this.account.address
return this.services.walletService.EOAAddress;
}

async isModuleInstalled(moduleTypeId: MODULE_TYPE, module: string, initData = '0x'): Promise<boolean> {
Expand Down Expand Up @@ -364,14 +363,7 @@ export class EtherspotWalletAPI extends BaseAccountAPI {
}

async signUserOpHash(userOpHash: string): Promise<string> {
const userOpHashHex = userOpHash as Hex;
const signature = await this.walletClient.signMessage(
{
message: { raw: userOpHashHex },
account: this.account,
});

return signature;
return await this.services.walletService.signUserOp(userOpHash as Hex);
}

async encodeBatch(targets: string[], values: BigNumberish[], datas: string[]): Promise<string> {
Expand Down
11 changes: 4 additions & 7 deletions src/sdk/base/HttpRpcClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,11 @@ const debug = Debug('aa.rpc');

export class HttpRpcClient {
private readonly publicClient: PublicClient;
private readonly walletClient: WalletClient;
initializing: Promise<void>;

constructor(readonly bundlerUrl: string, readonly entryPointAddress: string, readonly chainId: number, walletClient: WalletClient, publicClient: PublicClient) {
constructor(readonly bundlerUrl: string, readonly entryPointAddress: string, readonly chainId: number, publicClient: PublicClient) {
try {
this.publicClient = publicClient;
this.walletClient = walletClient;

this.initializing = this.validateChainId();
} catch (err) {
if (err.message.includes('failed response'))
Expand Down Expand Up @@ -57,7 +54,7 @@ export class HttpRpcClient {
async getVerificationGasInfo(tx: BaseAccountUserOperationStruct): Promise<any> {
const hexifiedUserOp = deepHexlify(await resolveProperties(tx));
try {
const response = await this.walletClient.request({
const response = await this.publicClient.request({
method: 'eth_estimateUserOperationGas',
params: [hexifiedUserOp, this.entryPointAddress]
});
Expand Down Expand Up @@ -96,7 +93,7 @@ export class HttpRpcClient {
const jsonRequestData: [BaseAccountUserOperationStruct, string] = [hexifiedUserOp, this.entryPointAddress];
await this.printUserOperation('eth_sendUserOperation', jsonRequestData);
//return await this.userOpJsonRpcProvider.send('eth_sendUserOperation', [hexifiedUserOp, this.entryPointAddress]);
return await this.walletClient.request({
return await this.publicClient.request({
method: 'eth_sendUserOperation',
params: [hexifiedUserOp, this.entryPointAddress]
});
Expand All @@ -113,7 +110,7 @@ export class HttpRpcClient {
// hexifiedUserOps,
// this.entryPointAddress,
// ]);
return await this.walletClient.request({
return await this.publicClient.request({
method: 'eth_sendAggregatedUserOperation',
params: [hexifiedUserOps, this.entryPointAddress]
});
Expand Down
2 changes: 2 additions & 0 deletions src/sdk/context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ErrorSubject, Service } from './common';
import { NetworkService } from './network';
import { WalletService } from './wallet';

export class Context {
readonly error$ = new ErrorSubject();
Expand All @@ -9,6 +10,7 @@ export class Context {
constructor(
readonly services: {
networkService: NetworkService;
walletService: WalletService;
},
) {
const items = [...Object.values(services)];
Expand Down
54 changes: 30 additions & 24 deletions src/sdk/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import { Factory, PaymasterApi, SdkOptions } from './interfaces';
import { Network } from "./network";
import { BatchUserOpsRequest, Exception, getGasFee, getViemAccount, getViemAddress, MODULE_TYPE, onRampApiKey, openUrl, UserOperation, UserOpsRequest } from "./common";
import {
BatchUserOpsRequest, Exception, getGasFee,
getViemAccount, getViemAddress, MODULE_TYPE,
onRampApiKey, openUrl, UserOperation, UserOpsRequest
} from "./common";
import {
EthereumProvider,
isWalletConnectProvider,
isWalletProvider,
MessagePayload,
WalletConnect2WalletProvider,
WalletProviderLike
} from './wallet';
import { DEFAULT_QUERY_PAGE_SIZE, Networks, onRamperAllNetworks } from './network/constants';
import { EtherspotWalletAPI, HttpRpcClient, VerifyingPaymasterAPI } from './base';
import { TransactionDetailsForUserOp, TransactionGasInfoForUserOp } from './base/TransactionDetailsForUserOp';
Expand All @@ -24,24 +36,27 @@ export class ModularSdk {
private chainId: number;
private factoryUsed: Factory;
private index: number;
private walletClient: WalletClient;
private publicClient: PublicClient;
private account: Account;
private providerUrl: string;

private userOpsBatch: BatchUserOpsRequest = { to: [], data: [], value: [] };

constructor({ privateKey } : {privateKey: string}, optionsLike: SdkOptions) {
constructor(walletProvider: WalletProviderLike, optionsLike: SdkOptions) {
let walletConnectProvider;
if (isWalletConnectProvider(walletProvider)) {
walletConnectProvider = new WalletConnect2WalletProvider(walletProvider as EthereumProvider);
} else if (!isWalletProvider(walletProvider)) {
throw new Exception('Invalid wallet provider');
}

const {
index,
chainId,
rpcProviderUrl,
accountAddress,
} = optionsLike;

if (!privateKey) throw new Exception('privateKey is required');

this.account = getViemAccount(privateKey);
this.chainId = chainId;
this.index = index ?? 0;

Expand All @@ -60,12 +75,6 @@ export class ModularSdk {

this.providerUrl = viemClientUrl;

this.walletClient = getWalletClientFromAccount({
rpcUrl: viemClientUrl,
chainId: chainId,
account: this.account
});

this.publicClient = getPublicClient({
chainId: chainId,
transport: http(
Expand All @@ -92,11 +101,15 @@ export class ModularSdk {
factoryAddress: walletFactoryAddress,
predefinedAccountAddress: accountAddress,
index: this.index,
account: this.account,
walletClient: this.walletClient,
wallet: walletProvider,
publicClient: this.publicClient,
})
this.bundler = new HttpRpcClient(optionsLike.bundlerProvider.url, entryPointAddress, chainId, this.walletClient, this.publicClient);
});
this.bundler = new HttpRpcClient(
optionsLike.bundlerProvider.url,
entryPointAddress,
chainId,
this.publicClient
);
}

get supportedNetworks(): Network[] {
Expand All @@ -110,10 +123,6 @@ export class ModularSdk {
this.etherspotWallet.context.destroy();
}

getWalletClient(): WalletClient {
return this.walletClient;
}

getPublicClient(): PublicClient {
return this.publicClient;
}
Expand All @@ -136,10 +145,7 @@ export class ModularSdk {
network: false,
});

return this.walletClient.signMessage({
message: message as Hex,
account: this.account
});
return await this.etherspotWallet.services.walletService.signMessage(message as Hex);
}

getEOAAddress(): Hex {
Expand Down
3 changes: 3 additions & 0 deletions src/sdk/wallet/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './interfaces';
export * from './providers';
export * from './wallet.service';
8 changes: 8 additions & 0 deletions src/sdk/wallet/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface Wallet {
address: string;
providerType: string;
}

export interface WalletOptions {
provider?: string;
}
43 changes: 43 additions & 0 deletions src/sdk/wallet/providers/dynamic.wallet-provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { NetworkNames, prepareNetworkName } from '../../network';
import { prepareAddress, UniqueSubject } from '../../common';
import { MessagePayload, WalletProvider } from './interfaces';
import { Hash, Hex, TransactionRequest } from 'viem';

export abstract class DynamicWalletProvider implements WalletProvider {
readonly address$ = new UniqueSubject<string>();
readonly networkName$ = new UniqueSubject<NetworkNames>();

protected constructor(readonly type: string) {
//
}

get address(): string {
return this.address$.value;
}

get networkName(): NetworkNames {
return this.networkName$.value;
}

abstract signMessage(message: any, validatorAddress?: string): Promise<string>;

abstract signUserOp(message: Hex): Promise<string>;

abstract signTypedData(msg: MessagePayload): Promise<string>

protected setAddress(address: string): void {
this.address$.next(prepareAddress(address));
}

protected setNetworkName(networkNameOrChainId: string | number): void {
this.networkName$.next(prepareNetworkName(networkNameOrChainId));
}

abstract eth_requestAccounts(address?: string): Promise<string[]>;

abstract eth_accounts(address?: string): Promise<string[]>;

abstract eth_sendTransaction(transaction: TransactionRequest): Promise<Hash>;

abstract eth_signTransaction(transaction: TransactionRequest): Promise<string>;
}
9 changes: 9 additions & 0 deletions src/sdk/wallet/providers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export * from './dynamic.wallet-provider';
export * from './interfaces';
export * from './key.wallet-provider';
export * from './meta-mask.wallet-provider';
export * from './utils';
export * from './wallet-connect.wallet-provider';
export * from './wallet-connect-2.wallet-provider';
export * from './web3.wallet-provider';
export * from './web3eip1193.wallet-provider';
Loading

0 comments on commit ee21abb

Please sign in to comment.