@mentaproject/core 0.5.15 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
- import type { RenameProperty } from './Utils';
2
- import type { Transport, Chain } from './';
3
- import type { Client as ViemClient } from 'viem';
4
- import type { SmartAccount, BundlerClientConfig } from 'viem/account-abstraction';
1
+ import type { RenameProperty } from "./Utils";
2
+ import type { Transport, Chain } from "./";
3
+ import type { Client as ViemClient } from "viem";
4
+ import type { SmartAccount, BundlerClientConfig } from "viem/account-abstraction";
5
5
  import type { SmartAccountClientConfig } from "permissionless";
6
6
  export type PermissionlessClientProperties<client extends ViemClient | undefined = ViemClient | undefined> = {
7
7
  client: client;
@@ -9,5 +9,14 @@ export type PermissionlessClientProperties<client extends ViemClient | undefined
9
9
  paymasterContext: BundlerClientConfig["paymasterContext"] | undefined;
10
10
  userOperation: BundlerClientConfig["userOperation"] | undefined;
11
11
  };
12
- export type CoreClient<TChain extends Chain | undefined = Chain | undefined, TAccount extends SmartAccount | undefined = SmartAccount | undefined> = ViemClient<Transport, TChain, TAccount> & PermissionlessClientProperties;
12
+ /**
13
+ * A basic viem Client used for standard RPC operations.
14
+ * This is the type returned by createClient before smart account setup.
15
+ */
16
+ export type CoreClient<TChain extends Chain | undefined = Chain | undefined> = ViemClient<Transport, TChain>;
17
+ /**
18
+ * A SmartAccountClient with permissionless properties.
19
+ * This is the type returned after setting up the smart account.
20
+ */
21
+ export type SmartAccountCoreClient<TChain extends Chain | undefined = Chain | undefined, TAccount extends SmartAccount | undefined = SmartAccount | undefined> = ViemClient<Transport, TChain, TAccount> & PermissionlessClientProperties;
13
22
  export type CoreClientConfig = RenameProperty<SmartAccountClientConfig, "bundlerTransport", "transport">;
@@ -10,6 +10,9 @@ export interface PasskeySigner extends LocalAccount {
10
10
  }
11
11
  export interface MentaAccountParams {
12
12
  signer: PasskeySigner;
13
+ /** Transport for ERC-4337 bundler calls */
13
14
  bundlerTransport: Transport;
15
+ /** Transport for standard Ethereum RPC calls (eth_getBlock, etc.) */
16
+ publicTransport: Transport;
14
17
  }
15
18
  export type MentaAccountClient = Awaited<ReturnType<typeof createMentaAccount>>;
@@ -1,7 +1,7 @@
1
1
  export type { AccessList, Address, Hash, Hex, BlockTag, Chain, Log, TransactionType, Quantity, AbiItem, Transport, Withdrawal, Transaction, } from "viem";
2
2
  export type { GetEnsAddressReturnType, GetEnsAvatarReturnType, GetEnsNameReturnType, GetEnsResolverReturnType, GetEnsTextReturnType, CallReturnType, CreateAccessListReturnType, CreateBlockFilterReturnType, CreateContractEventFilterReturnType, CreateEventFilterReturnType, CreatePendingTransactionFilterReturnType, EstimateContractGasReturnType, EstimateFeesPerGasReturnType, EstimateMaxPriorityFeePerGasReturnType, EstimateGasReturnType, GetBalanceReturnType, GetBlobBaseFeeReturnType, GetBlockReturnType, GetBlockNumberReturnType, GetBlockTransactionCountReturnType, GetChainIdReturnType, GetCodeReturnType, GetBytecodeReturnType, GetContractEventsReturnType, GetEip712DomainReturnType, GetFeeHistoryReturnType, GetFilterChangesReturnType, GetFilterLogsReturnType, GetGasPriceReturnType, GetLogsReturnType, GetStorageAtReturnType, GetTransactionConfirmationsReturnType, GetTransactionCountReturnType, GetTransactionReturnType, GetTransactionReceiptReturnType, MulticallReturnType, SimulateBlocksReturnType, SimulateContractReturnType, SimulateCallsReturnType, WatchBlocksReturnType, WatchBlockNumberReturnType, WatchEventReturnType, WatchContractEventReturnType, WatchPendingTransactionsReturnType, ReadContractReturnType, GetProofReturnType, WaitForTransactionReceiptReturnType, SendTransactionReturnType, SignMessageReturnType, SignTypedDataReturnType, WriteContractReturnType, GetEnsAddressParameters, GetEnsAvatarParameters, GetEnsNameParameters, GetEnsResolverParameters, GetEnsTextParameters, CallParameters, CreateAccessListParameters, CreateContractEventFilterParameters, CreateEventFilterParameters, EstimateContractGasParameters, EstimateFeesPerGasParameters, EstimateMaxPriorityFeePerGasParameters, EstimateGasParameters, GetBalanceParameters, GetBlockParameters, GetBlockNumberParameters, GetBlockTransactionCountParameters, GetCodeParameters, GetBytecodeParameters, GetContractEventsParameters, GetEip712DomainParameters, GetFeeHistoryParameters, GetFilterChangesParameters, GetFilterLogsParameters, GetLogsParameters, GetStorageAtParameters, GetTransactionConfirmationsParameters, GetTransactionCountParameters, GetTransactionParameters, GetTransactionReceiptParameters, MulticallParameters, SimulateBlocksParameters, SimulateContractParameters, SimulateCallsParameters, WatchBlocksParameters, WatchBlockNumberParameters, WatchEventParameters, WatchContractEventParameters, WatchPendingTransactionsParameters, ReadContractParameters, GetProofParameters, WaitForTransactionReceiptParameters, SendTransactionParameters, SignMessageParameters, SignTypedDataParameters, WriteContractParameters, } from "viem";
3
3
  export type { AbiError, AbiConstructor, AbiFunction, AbiEvent, AbiParameter, AbiParameterToPrimitiveType, } from "abitype";
4
- export type { CoreClient, CoreClientConfig } from "./CoreClient";
4
+ export type { CoreClient, SmartAccountCoreClient, CoreClientConfig } from "./CoreClient";
5
5
  export { TraceFilterParameters, TraceFilterReturnType, TraceTransactionParameters, TraceTransactionReturnType, TraceBlockParameters, TraceBlockReturnType, TraceAction, TraceActionResult, TraceEntry, } from "./Trace";
6
6
  export { FetchBlockRangeParameters, onBlockRangeCallback, BlockRange, } from "./BlockRangeFetcher";
7
7
  export { TransactionOptions } from "./Transaction";
@@ -0,0 +1,22 @@
1
+ import type { Transport } from "viem";
2
+ /**
3
+ * Creates a transport that routes requests between a public RPC and a bundler RPC.
4
+ *
5
+ * Bundler-specific methods (ERC-4337) are routed to the bundler transport,
6
+ * while all other methods (eth_getBlockByNumber, eth_call, etc.) are routed
7
+ * to the public transport.
8
+ *
9
+ * @param publicTransport - Transport for standard Ethereum RPC calls
10
+ * @param bundlerTransport - Transport for ERC-4337 bundler calls
11
+ * @returns A unified transport that routes requests appropriately
12
+ *
13
+ * @example
14
+ * import { http } from 'viem';
15
+ * import { createRoutedTransport } from '@mentaproject/core/utils';
16
+ *
17
+ * const transport = createRoutedTransport(
18
+ * http('https://eth-mainnet.g.alchemy.com/v2/...'),
19
+ * http('https://api.pimlico.io/v2/1/rpc?apikey=...')
20
+ * );
21
+ */
22
+ export declare function createRoutedTransport(publicTransport: Transport, bundlerTransport: Transport): Transport;
@@ -1,3 +1,4 @@
1
1
  export * from 'viem/utils';
2
2
  export { bytesToAddress, bytes32ToAddress } from './bytesToAddress';
3
3
  export { nonZeroAddress } from './nonZeroAddress';
4
+ export { createRoutedTransport } from './createRoutedTransport';
@@ -33,8 +33,67 @@ const bytes32ToAddress = (bytes) => {
33
33
 
34
34
  const nonZeroAddress = (address) => address === viem.zeroAddress ? undefined : address;
35
35
 
36
+ /**
37
+ * RPC methods that should be routed to the bundler.
38
+ * All other methods will be routed to the public RPC.
39
+ */
40
+ const BUNDLER_METHODS = new Set([
41
+ // ERC-4337 standard methods
42
+ "eth_sendUserOperation",
43
+ "eth_estimateUserOperationGas",
44
+ "eth_getUserOperationByHash",
45
+ "eth_getUserOperationReceipt",
46
+ "eth_supportedEntryPoints",
47
+ // Pimlico-specific methods
48
+ "pimlico_getUserOperationGasPrice",
49
+ "pimlico_getUserOperationStatus",
50
+ "pimlico_sendCompressedUserOperation",
51
+ // pm_ paymaster methods (used by some bundlers)
52
+ "pm_getPaymasterData",
53
+ "pm_getPaymasterStubData",
54
+ "pm_sponsorUserOperation",
55
+ "pm_validateSponsorshipPolicies",
56
+ ]);
57
+ /**
58
+ * Creates a transport that routes requests between a public RPC and a bundler RPC.
59
+ *
60
+ * Bundler-specific methods (ERC-4337) are routed to the bundler transport,
61
+ * while all other methods (eth_getBlockByNumber, eth_call, etc.) are routed
62
+ * to the public transport.
63
+ *
64
+ * @param publicTransport - Transport for standard Ethereum RPC calls
65
+ * @param bundlerTransport - Transport for ERC-4337 bundler calls
66
+ * @returns A unified transport that routes requests appropriately
67
+ *
68
+ * @example
69
+ * import { http } from 'viem';
70
+ * import { createRoutedTransport } from '@mentaproject/core/utils';
71
+ *
72
+ * const transport = createRoutedTransport(
73
+ * http('https://eth-mainnet.g.alchemy.com/v2/...'),
74
+ * http('https://api.pimlico.io/v2/1/rpc?apikey=...')
75
+ * );
76
+ */
77
+ function createRoutedTransport(publicTransport, bundlerTransport) {
78
+ return (params) => {
79
+ const publicClient = publicTransport(params);
80
+ const bundlerClient = bundlerTransport(params);
81
+ const request = async ({ method, params: reqParams }) => {
82
+ if (BUNDLER_METHODS.has(method)) {
83
+ return bundlerClient.request({ method, params: reqParams });
84
+ }
85
+ return publicClient.request({ method, params: reqParams });
86
+ };
87
+ return {
88
+ ...publicClient,
89
+ request,
90
+ };
91
+ };
92
+ }
93
+
36
94
  exports.bytes32ToAddress = bytes32ToAddress;
37
95
  exports.bytesToAddress = bytesToAddress;
96
+ exports.createRoutedTransport = createRoutedTransport;
38
97
  exports.nonZeroAddress = nonZeroAddress;
39
98
  Object.keys(utils).forEach(function (k) {
40
99
  if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/utils/bytesToAddress.ts","../../src/utils/nonZeroAddress.ts"],"sourcesContent":["import { getAddress, slice } from \".\";\nimport { Address, Hex } from \"../types\";\n\n/**\n * Helper function to convert a bytes value to an address.\n * @param bytes The bytes value to convert.\n * @param startByteIndex The index of the first byte to extract from the bytes value.\n * @returns The address or undefined if the conversion failed.\n */\nexport const bytesToAddress = (bytes: Hex, startByteIndex: number): Address => {\n if (startByteIndex < 0) throw new Error(`startByteIndex must be greater than or equal to 0, got ${startByteIndex}`);\n if (!bytes || bytes.length < startByteIndex + 20) throw new Error(`Bytes value must be at least ${startByteIndex + 20} characters long, got ${bytes?.length ?? 0}`);\n\n // Extracts 20 bytes starting from startByteIndex\n const addressBytes = slice(bytes, startByteIndex, startByteIndex + 20);\n\n if (addressBytes.length !== 42) throw new Error(`Address bytes must be 42 characters long, got ${addressBytes.length}`);\n return getAddress(addressBytes);\n};\n\n/**\n * Helper function to convert a bytes32 value to an address.\n * @param bytes The bytes32 value to convert.\n * @returns The address or undefined if the conversion failed.\n */\nexport const bytes32ToAddress = (bytes: Hex): Address => {\n if (!bytes || bytes.length !== 66) throw new Error(`Bytes32 value must be 66 characters long, got ${bytes?.length ?? 0}`);\n\n return bytesToAddress(bytes, 12);\n};","import { zeroAddress } from \"..\";\nimport { Address } from \"../types\";\n\nexport const nonZeroAddress = (address: Address): Address | undefined => address === zeroAddress ? undefined : address;"],"names":["slice","getAddress","zeroAddress"],"mappings":";;;;;AAGA;;;;;AAKG;MACU,cAAc,GAAG,CAAC,KAAU,EAAE,cAAsB,KAAa;IAC1E,IAAI,cAAc,GAAG,CAAC;AAAE,QAAA,MAAM,IAAI,KAAK,CAAC,0DAA0D,cAAc,CAAA,CAAE,CAAC;IACnH,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,cAAc,GAAG,EAAE;AAAE,QAAA,MAAM,IAAI,KAAK,CAAC,CAAA,6BAAA,EAAgC,cAAc,GAAG,EAAE,CAAA,sBAAA,EAAyB,KAAK,EAAE,MAAM,IAAI,CAAC,CAAA,CAAE,CAAC;;AAGnK,IAAA,MAAM,YAAY,GAAGA,WAAK,CAAC,KAAK,EAAE,cAAc,EAAE,cAAc,GAAG,EAAE,CAAC;AAEtE,IAAA,IAAI,YAAY,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,CAAA,8CAAA,EAAiD,YAAY,CAAC,MAAM,CAAA,CAAE,CAAC;AACvH,IAAA,OAAOC,gBAAU,CAAC,YAAY,CAAC;AACnC;AAEA;;;;AAIG;AACI,MAAM,gBAAgB,GAAG,CAAC,KAAU,KAAa;AACpD,IAAA,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,CAAA,8CAAA,EAAiD,KAAK,EAAE,MAAM,IAAI,CAAC,CAAA,CAAE,CAAC;AAEzH,IAAA,OAAO,cAAc,CAAC,KAAK,EAAE,EAAE,CAAC;AACpC;;MC1Ba,cAAc,GAAG,CAAC,OAAgB,KAA0B,OAAO,KAAKC,gBAAW,GAAG,SAAS,GAAG;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/utils/bytesToAddress.ts","../../src/utils/nonZeroAddress.ts","../../src/utils/createRoutedTransport.ts"],"sourcesContent":["import { getAddress, slice } from \".\";\nimport { Address, Hex } from \"../types\";\n\n/**\n * Helper function to convert a bytes value to an address.\n * @param bytes The bytes value to convert.\n * @param startByteIndex The index of the first byte to extract from the bytes value.\n * @returns The address or undefined if the conversion failed.\n */\nexport const bytesToAddress = (bytes: Hex, startByteIndex: number): Address => {\n if (startByteIndex < 0) throw new Error(`startByteIndex must be greater than or equal to 0, got ${startByteIndex}`);\n if (!bytes || bytes.length < startByteIndex + 20) throw new Error(`Bytes value must be at least ${startByteIndex + 20} characters long, got ${bytes?.length ?? 0}`);\n\n // Extracts 20 bytes starting from startByteIndex\n const addressBytes = slice(bytes, startByteIndex, startByteIndex + 20);\n\n if (addressBytes.length !== 42) throw new Error(`Address bytes must be 42 characters long, got ${addressBytes.length}`);\n return getAddress(addressBytes);\n};\n\n/**\n * Helper function to convert a bytes32 value to an address.\n * @param bytes The bytes32 value to convert.\n * @returns The address or undefined if the conversion failed.\n */\nexport const bytes32ToAddress = (bytes: Hex): Address => {\n if (!bytes || bytes.length !== 66) throw new Error(`Bytes32 value must be 66 characters long, got ${bytes?.length ?? 0}`);\n\n return bytesToAddress(bytes, 12);\n};","import { zeroAddress } from \"..\";\nimport { Address } from \"../types\";\n\nexport const nonZeroAddress = (address: Address): Address | undefined => address === zeroAddress ? undefined : address;","import type { EIP1193RequestFn, Transport } from \"viem\";\n\n/**\n * RPC methods that should be routed to the bundler.\n * All other methods will be routed to the public RPC.\n */\nconst BUNDLER_METHODS = new Set([\n // ERC-4337 standard methods\n \"eth_sendUserOperation\",\n \"eth_estimateUserOperationGas\",\n \"eth_getUserOperationByHash\",\n \"eth_getUserOperationReceipt\",\n \"eth_supportedEntryPoints\",\n // Pimlico-specific methods\n \"pimlico_getUserOperationGasPrice\",\n \"pimlico_getUserOperationStatus\",\n \"pimlico_sendCompressedUserOperation\",\n // pm_ paymaster methods (used by some bundlers)\n \"pm_getPaymasterData\",\n \"pm_getPaymasterStubData\",\n \"pm_sponsorUserOperation\",\n \"pm_validateSponsorshipPolicies\",\n]);\n\n/**\n * Creates a transport that routes requests between a public RPC and a bundler RPC.\n *\n * Bundler-specific methods (ERC-4337) are routed to the bundler transport,\n * while all other methods (eth_getBlockByNumber, eth_call, etc.) are routed\n * to the public transport.\n *\n * @param publicTransport - Transport for standard Ethereum RPC calls\n * @param bundlerTransport - Transport for ERC-4337 bundler calls\n * @returns A unified transport that routes requests appropriately\n *\n * @example\n * import { http } from 'viem';\n * import { createRoutedTransport } from '@mentaproject/core/utils';\n *\n * const transport = createRoutedTransport(\n * http('https://eth-mainnet.g.alchemy.com/v2/...'),\n * http('https://api.pimlico.io/v2/1/rpc?apikey=...')\n * );\n */\nexport function createRoutedTransport(\n publicTransport: Transport,\n bundlerTransport: Transport,\n): Transport {\n return (params) => {\n const publicClient = publicTransport(params);\n const bundlerClient = bundlerTransport(params);\n\n const request: EIP1193RequestFn = async ({ method, params: reqParams }) => {\n if (BUNDLER_METHODS.has(method)) {\n return bundlerClient.request({ method, params: reqParams } as any);\n }\n return publicClient.request({ method, params: reqParams } as any);\n };\n\n return {\n ...publicClient,\n request,\n };\n };\n}\n"],"names":["slice","getAddress","zeroAddress"],"mappings":";;;;;AAGA;;;;;AAKG;MACU,cAAc,GAAG,CAAC,KAAU,EAAE,cAAsB,KAAa;IAC1E,IAAI,cAAc,GAAG,CAAC;AAAE,QAAA,MAAM,IAAI,KAAK,CAAC,0DAA0D,cAAc,CAAA,CAAE,CAAC;IACnH,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,cAAc,GAAG,EAAE;AAAE,QAAA,MAAM,IAAI,KAAK,CAAC,CAAA,6BAAA,EAAgC,cAAc,GAAG,EAAE,CAAA,sBAAA,EAAyB,KAAK,EAAE,MAAM,IAAI,CAAC,CAAA,CAAE,CAAC;;AAGnK,IAAA,MAAM,YAAY,GAAGA,WAAK,CAAC,KAAK,EAAE,cAAc,EAAE,cAAc,GAAG,EAAE,CAAC;AAEtE,IAAA,IAAI,YAAY,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,CAAA,8CAAA,EAAiD,YAAY,CAAC,MAAM,CAAA,CAAE,CAAC;AACvH,IAAA,OAAOC,gBAAU,CAAC,YAAY,CAAC;AACnC;AAEA;;;;AAIG;AACI,MAAM,gBAAgB,GAAG,CAAC,KAAU,KAAa;AACpD,IAAA,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,CAAA,8CAAA,EAAiD,KAAK,EAAE,MAAM,IAAI,CAAC,CAAA,CAAE,CAAC;AAEzH,IAAA,OAAO,cAAc,CAAC,KAAK,EAAE,EAAE,CAAC;AACpC;;MC1Ba,cAAc,GAAG,CAAC,OAAgB,KAA0B,OAAO,KAAKC,gBAAW,GAAG,SAAS,GAAG;;ACD/G;;;AAGG;AACH,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;;IAE9B,uBAAuB;IACvB,8BAA8B;IAC9B,4BAA4B;IAC5B,6BAA6B;IAC7B,0BAA0B;;IAE1B,kCAAkC;IAClC,gCAAgC;IAChC,qCAAqC;;IAErC,qBAAqB;IACrB,yBAAyB;IACzB,yBAAyB;IACzB,gCAAgC;AACjC,CAAA,CAAC;AAEF;;;;;;;;;;;;;;;;;;;AAmBG;AACG,SAAU,qBAAqB,CACnC,eAA0B,EAC1B,gBAA2B,EAAA;IAE3B,OAAO,CAAC,MAAM,KAAI;AAChB,QAAA,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC;AAC5C,QAAA,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAC;AAE9C,QAAA,MAAM,OAAO,GAAqB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAI;AACxE,YAAA,IAAI,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;AAC/B,gBAAA,OAAO,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAS,CAAC;YACpE;AACA,YAAA,OAAO,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAS,CAAC;AACnE,QAAA,CAAC;QAED,OAAO;AACL,YAAA,GAAG,YAAY;YACf,OAAO;SACR;AACH,IAAA,CAAC;AACH;;;;;;;;;;;;;"}
@@ -32,5 +32,63 @@ const bytes32ToAddress = (bytes) => {
32
32
 
33
33
  const nonZeroAddress = (address) => address === zeroAddress ? undefined : address;
34
34
 
35
- export { bytes32ToAddress, bytesToAddress, nonZeroAddress };
35
+ /**
36
+ * RPC methods that should be routed to the bundler.
37
+ * All other methods will be routed to the public RPC.
38
+ */
39
+ const BUNDLER_METHODS = new Set([
40
+ // ERC-4337 standard methods
41
+ "eth_sendUserOperation",
42
+ "eth_estimateUserOperationGas",
43
+ "eth_getUserOperationByHash",
44
+ "eth_getUserOperationReceipt",
45
+ "eth_supportedEntryPoints",
46
+ // Pimlico-specific methods
47
+ "pimlico_getUserOperationGasPrice",
48
+ "pimlico_getUserOperationStatus",
49
+ "pimlico_sendCompressedUserOperation",
50
+ // pm_ paymaster methods (used by some bundlers)
51
+ "pm_getPaymasterData",
52
+ "pm_getPaymasterStubData",
53
+ "pm_sponsorUserOperation",
54
+ "pm_validateSponsorshipPolicies",
55
+ ]);
56
+ /**
57
+ * Creates a transport that routes requests between a public RPC and a bundler RPC.
58
+ *
59
+ * Bundler-specific methods (ERC-4337) are routed to the bundler transport,
60
+ * while all other methods (eth_getBlockByNumber, eth_call, etc.) are routed
61
+ * to the public transport.
62
+ *
63
+ * @param publicTransport - Transport for standard Ethereum RPC calls
64
+ * @param bundlerTransport - Transport for ERC-4337 bundler calls
65
+ * @returns A unified transport that routes requests appropriately
66
+ *
67
+ * @example
68
+ * import { http } from 'viem';
69
+ * import { createRoutedTransport } from '@mentaproject/core/utils';
70
+ *
71
+ * const transport = createRoutedTransport(
72
+ * http('https://eth-mainnet.g.alchemy.com/v2/...'),
73
+ * http('https://api.pimlico.io/v2/1/rpc?apikey=...')
74
+ * );
75
+ */
76
+ function createRoutedTransport(publicTransport, bundlerTransport) {
77
+ return (params) => {
78
+ const publicClient = publicTransport(params);
79
+ const bundlerClient = bundlerTransport(params);
80
+ const request = async ({ method, params: reqParams }) => {
81
+ if (BUNDLER_METHODS.has(method)) {
82
+ return bundlerClient.request({ method, params: reqParams });
83
+ }
84
+ return publicClient.request({ method, params: reqParams });
85
+ };
86
+ return {
87
+ ...publicClient,
88
+ request,
89
+ };
90
+ };
91
+ }
92
+
93
+ export { bytes32ToAddress, bytesToAddress, createRoutedTransport, nonZeroAddress };
36
94
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../src/utils/bytesToAddress.ts","../../src/utils/nonZeroAddress.ts"],"sourcesContent":["import { getAddress, slice } from \".\";\nimport { Address, Hex } from \"../types\";\n\n/**\n * Helper function to convert a bytes value to an address.\n * @param bytes The bytes value to convert.\n * @param startByteIndex The index of the first byte to extract from the bytes value.\n * @returns The address or undefined if the conversion failed.\n */\nexport const bytesToAddress = (bytes: Hex, startByteIndex: number): Address => {\n if (startByteIndex < 0) throw new Error(`startByteIndex must be greater than or equal to 0, got ${startByteIndex}`);\n if (!bytes || bytes.length < startByteIndex + 20) throw new Error(`Bytes value must be at least ${startByteIndex + 20} characters long, got ${bytes?.length ?? 0}`);\n\n // Extracts 20 bytes starting from startByteIndex\n const addressBytes = slice(bytes, startByteIndex, startByteIndex + 20);\n\n if (addressBytes.length !== 42) throw new Error(`Address bytes must be 42 characters long, got ${addressBytes.length}`);\n return getAddress(addressBytes);\n};\n\n/**\n * Helper function to convert a bytes32 value to an address.\n * @param bytes The bytes32 value to convert.\n * @returns The address or undefined if the conversion failed.\n */\nexport const bytes32ToAddress = (bytes: Hex): Address => {\n if (!bytes || bytes.length !== 66) throw new Error(`Bytes32 value must be 66 characters long, got ${bytes?.length ?? 0}`);\n\n return bytesToAddress(bytes, 12);\n};","import { zeroAddress } from \"..\";\nimport { Address } from \"../types\";\n\nexport const nonZeroAddress = (address: Address): Address | undefined => address === zeroAddress ? undefined : address;"],"names":[],"mappings":";;;;AAGA;;;;;AAKG;MACU,cAAc,GAAG,CAAC,KAAU,EAAE,cAAsB,KAAa;IAC1E,IAAI,cAAc,GAAG,CAAC;AAAE,QAAA,MAAM,IAAI,KAAK,CAAC,0DAA0D,cAAc,CAAA,CAAE,CAAC;IACnH,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,cAAc,GAAG,EAAE;AAAE,QAAA,MAAM,IAAI,KAAK,CAAC,CAAA,6BAAA,EAAgC,cAAc,GAAG,EAAE,CAAA,sBAAA,EAAyB,KAAK,EAAE,MAAM,IAAI,CAAC,CAAA,CAAE,CAAC;;AAGnK,IAAA,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE,cAAc,GAAG,EAAE,CAAC;AAEtE,IAAA,IAAI,YAAY,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,CAAA,8CAAA,EAAiD,YAAY,CAAC,MAAM,CAAA,CAAE,CAAC;AACvH,IAAA,OAAO,UAAU,CAAC,YAAY,CAAC;AACnC;AAEA;;;;AAIG;AACI,MAAM,gBAAgB,GAAG,CAAC,KAAU,KAAa;AACpD,IAAA,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,CAAA,8CAAA,EAAiD,KAAK,EAAE,MAAM,IAAI,CAAC,CAAA,CAAE,CAAC;AAEzH,IAAA,OAAO,cAAc,CAAC,KAAK,EAAE,EAAE,CAAC;AACpC;;MC1Ba,cAAc,GAAG,CAAC,OAAgB,KAA0B,OAAO,KAAK,WAAW,GAAG,SAAS,GAAG;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":["../../src/utils/bytesToAddress.ts","../../src/utils/nonZeroAddress.ts","../../src/utils/createRoutedTransport.ts"],"sourcesContent":["import { getAddress, slice } from \".\";\nimport { Address, Hex } from \"../types\";\n\n/**\n * Helper function to convert a bytes value to an address.\n * @param bytes The bytes value to convert.\n * @param startByteIndex The index of the first byte to extract from the bytes value.\n * @returns The address or undefined if the conversion failed.\n */\nexport const bytesToAddress = (bytes: Hex, startByteIndex: number): Address => {\n if (startByteIndex < 0) throw new Error(`startByteIndex must be greater than or equal to 0, got ${startByteIndex}`);\n if (!bytes || bytes.length < startByteIndex + 20) throw new Error(`Bytes value must be at least ${startByteIndex + 20} characters long, got ${bytes?.length ?? 0}`);\n\n // Extracts 20 bytes starting from startByteIndex\n const addressBytes = slice(bytes, startByteIndex, startByteIndex + 20);\n\n if (addressBytes.length !== 42) throw new Error(`Address bytes must be 42 characters long, got ${addressBytes.length}`);\n return getAddress(addressBytes);\n};\n\n/**\n * Helper function to convert a bytes32 value to an address.\n * @param bytes The bytes32 value to convert.\n * @returns The address or undefined if the conversion failed.\n */\nexport const bytes32ToAddress = (bytes: Hex): Address => {\n if (!bytes || bytes.length !== 66) throw new Error(`Bytes32 value must be 66 characters long, got ${bytes?.length ?? 0}`);\n\n return bytesToAddress(bytes, 12);\n};","import { zeroAddress } from \"..\";\nimport { Address } from \"../types\";\n\nexport const nonZeroAddress = (address: Address): Address | undefined => address === zeroAddress ? undefined : address;","import type { EIP1193RequestFn, Transport } from \"viem\";\n\n/**\n * RPC methods that should be routed to the bundler.\n * All other methods will be routed to the public RPC.\n */\nconst BUNDLER_METHODS = new Set([\n // ERC-4337 standard methods\n \"eth_sendUserOperation\",\n \"eth_estimateUserOperationGas\",\n \"eth_getUserOperationByHash\",\n \"eth_getUserOperationReceipt\",\n \"eth_supportedEntryPoints\",\n // Pimlico-specific methods\n \"pimlico_getUserOperationGasPrice\",\n \"pimlico_getUserOperationStatus\",\n \"pimlico_sendCompressedUserOperation\",\n // pm_ paymaster methods (used by some bundlers)\n \"pm_getPaymasterData\",\n \"pm_getPaymasterStubData\",\n \"pm_sponsorUserOperation\",\n \"pm_validateSponsorshipPolicies\",\n]);\n\n/**\n * Creates a transport that routes requests between a public RPC and a bundler RPC.\n *\n * Bundler-specific methods (ERC-4337) are routed to the bundler transport,\n * while all other methods (eth_getBlockByNumber, eth_call, etc.) are routed\n * to the public transport.\n *\n * @param publicTransport - Transport for standard Ethereum RPC calls\n * @param bundlerTransport - Transport for ERC-4337 bundler calls\n * @returns A unified transport that routes requests appropriately\n *\n * @example\n * import { http } from 'viem';\n * import { createRoutedTransport } from '@mentaproject/core/utils';\n *\n * const transport = createRoutedTransport(\n * http('https://eth-mainnet.g.alchemy.com/v2/...'),\n * http('https://api.pimlico.io/v2/1/rpc?apikey=...')\n * );\n */\nexport function createRoutedTransport(\n publicTransport: Transport,\n bundlerTransport: Transport,\n): Transport {\n return (params) => {\n const publicClient = publicTransport(params);\n const bundlerClient = bundlerTransport(params);\n\n const request: EIP1193RequestFn = async ({ method, params: reqParams }) => {\n if (BUNDLER_METHODS.has(method)) {\n return bundlerClient.request({ method, params: reqParams } as any);\n }\n return publicClient.request({ method, params: reqParams } as any);\n };\n\n return {\n ...publicClient,\n request,\n };\n };\n}\n"],"names":[],"mappings":";;;;AAGA;;;;;AAKG;MACU,cAAc,GAAG,CAAC,KAAU,EAAE,cAAsB,KAAa;IAC1E,IAAI,cAAc,GAAG,CAAC;AAAE,QAAA,MAAM,IAAI,KAAK,CAAC,0DAA0D,cAAc,CAAA,CAAE,CAAC;IACnH,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,cAAc,GAAG,EAAE;AAAE,QAAA,MAAM,IAAI,KAAK,CAAC,CAAA,6BAAA,EAAgC,cAAc,GAAG,EAAE,CAAA,sBAAA,EAAyB,KAAK,EAAE,MAAM,IAAI,CAAC,CAAA,CAAE,CAAC;;AAGnK,IAAA,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE,cAAc,GAAG,EAAE,CAAC;AAEtE,IAAA,IAAI,YAAY,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,CAAA,8CAAA,EAAiD,YAAY,CAAC,MAAM,CAAA,CAAE,CAAC;AACvH,IAAA,OAAO,UAAU,CAAC,YAAY,CAAC;AACnC;AAEA;;;;AAIG;AACI,MAAM,gBAAgB,GAAG,CAAC,KAAU,KAAa;AACpD,IAAA,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,CAAA,8CAAA,EAAiD,KAAK,EAAE,MAAM,IAAI,CAAC,CAAA,CAAE,CAAC;AAEzH,IAAA,OAAO,cAAc,CAAC,KAAK,EAAE,EAAE,CAAC;AACpC;;MC1Ba,cAAc,GAAG,CAAC,OAAgB,KAA0B,OAAO,KAAK,WAAW,GAAG,SAAS,GAAG;;ACD/G;;;AAGG;AACH,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;;IAE9B,uBAAuB;IACvB,8BAA8B;IAC9B,4BAA4B;IAC5B,6BAA6B;IAC7B,0BAA0B;;IAE1B,kCAAkC;IAClC,gCAAgC;IAChC,qCAAqC;;IAErC,qBAAqB;IACrB,yBAAyB;IACzB,yBAAyB;IACzB,gCAAgC;AACjC,CAAA,CAAC;AAEF;;;;;;;;;;;;;;;;;;;AAmBG;AACG,SAAU,qBAAqB,CACnC,eAA0B,EAC1B,gBAA2B,EAAA;IAE3B,OAAO,CAAC,MAAM,KAAI;AAChB,QAAA,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC;AAC5C,QAAA,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAC;AAE9C,QAAA,MAAM,OAAO,GAAqB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAI;AACxE,YAAA,IAAI,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;AAC/B,gBAAA,OAAO,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAS,CAAC;YACpE;AACA,YAAA,OAAO,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAS,CAAC;AACnE,QAAA,CAAC;QAED,OAAO;AACL,YAAA,GAAG,YAAY;YACf,OAAO;SACR;AACH,IAAA,CAAC;AACH;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mentaproject/core",
3
- "version": "0.5.15",
3
+ "version": "0.6.1",
4
4
  "description": "Core library for menta packages, it includes all basic evm instances like Account, Transactions, Blocks etc...",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -7,19 +7,19 @@ import { entryPoint07Address } from "../account-abstraction";
7
7
  import { toKernelSmartAccount } from "permissionless/accounts";
8
8
  import { createSmartAccountClient } from "permissionless";
9
9
  import { erc7579Actions } from "permissionless/actions/erc7579";
10
+ import { createRoutedTransport } from "../utils/createRoutedTransport";
10
11
  import type {
11
12
  Client,
12
13
  Transport,
13
14
  Chain,
14
- JsonRpcAccount,
15
- LocalAccount,
15
+ Account,
16
16
  } from "viem";
17
17
 
18
18
  export async function createMentaAccount<TChain extends Chain | undefined>(
19
- client: Client<Transport, TChain, JsonRpcAccount | LocalAccount | undefined>,
19
+ client: Client<Transport, TChain, Account | undefined>,
20
20
  params: MentaAccountParams,
21
21
  ) {
22
- const validator = await toPasskeyValidator(client, {
22
+ const validator = await toPasskeyValidator(client as any, {
23
23
  webAuthnKey: params.signer,
24
24
  entryPoint: {
25
25
  address: entryPoint07Address,
@@ -31,11 +31,18 @@ export async function createMentaAccount<TChain extends Chain | undefined>(
31
31
 
32
32
  const kernel = await toKernelSmartAccount({
33
33
  owners: [validator],
34
- client: client,
34
+ client: client as any,
35
35
  });
36
36
 
37
+ // Create a routed transport that sends bundler methods to the bundler
38
+ // and all other RPC calls to the public transport
39
+ const routedTransport = createRoutedTransport(
40
+ params.publicTransport,
41
+ params.bundlerTransport,
42
+ );
43
+
37
44
  return createSmartAccountClient({
38
45
  account: kernel,
39
- bundlerTransport: params.bundlerTransport,
46
+ bundlerTransport: routedTransport,
40
47
  }).extend(erc7579Actions());
41
48
  }
@@ -1,22 +1,40 @@
1
- import type{ RenameProperty } from './Utils';
2
- import type { Transport, Chain } from './';
1
+ import type { RenameProperty } from "./Utils";
2
+ import type { Transport, Chain } from "./";
3
3
 
4
- import type { Client as ViemClient } from 'viem';
5
- import type { SmartAccount, BundlerClientConfig } from 'viem/account-abstraction';
4
+ import type { Client as ViemClient } from "viem";
5
+ import type {
6
+ SmartAccount,
7
+ BundlerClientConfig,
8
+ } from "viem/account-abstraction";
6
9
  import type { SmartAccountClientConfig } from "permissionless";
7
10
 
8
11
  export type PermissionlessClientProperties<
9
- client extends ViemClient | undefined = ViemClient | undefined,
12
+ client extends ViemClient | undefined = ViemClient | undefined,
10
13
  > = {
11
- client: client
12
- paymaster: BundlerClientConfig["paymaster"] | undefined
13
- paymasterContext: BundlerClientConfig["paymasterContext"] | undefined
14
- userOperation: BundlerClientConfig["userOperation"] | undefined
15
- }
14
+ client: client;
15
+ paymaster: BundlerClientConfig["paymaster"] | undefined;
16
+ paymasterContext: BundlerClientConfig["paymasterContext"] | undefined;
17
+ userOperation: BundlerClientConfig["userOperation"] | undefined;
18
+ };
16
19
 
17
- export type CoreClient<
18
- TChain extends Chain | undefined = Chain | undefined,
19
- TAccount extends SmartAccount | undefined = SmartAccount | undefined,
20
+ /**
21
+ * A basic viem Client used for standard RPC operations.
22
+ * This is the type returned by createClient before smart account setup.
23
+ */
24
+ export type CoreClient<TChain extends Chain | undefined = Chain | undefined> =
25
+ ViemClient<Transport, TChain>;
26
+
27
+ /**
28
+ * A SmartAccountClient with permissionless properties.
29
+ * This is the type returned after setting up the smart account.
30
+ */
31
+ export type SmartAccountCoreClient<
32
+ TChain extends Chain | undefined = Chain | undefined,
33
+ TAccount extends SmartAccount | undefined = SmartAccount | undefined,
20
34
  > = ViemClient<Transport, TChain, TAccount> & PermissionlessClientProperties;
21
35
 
22
- export type CoreClientConfig = RenameProperty<SmartAccountClientConfig, "bundlerTransport", "transport">;
36
+ export type CoreClientConfig = RenameProperty<
37
+ SmartAccountClientConfig,
38
+ "bundlerTransport",
39
+ "transport"
40
+ >;
@@ -12,7 +12,10 @@ export interface PasskeySigner extends LocalAccount {
12
12
 
13
13
  export interface MentaAccountParams {
14
14
  signer: PasskeySigner;
15
+ /** Transport for ERC-4337 bundler calls */
15
16
  bundlerTransport: Transport;
17
+ /** Transport for standard Ethereum RPC calls (eth_getBlock, etc.) */
18
+ publicTransport: Transport;
16
19
  }
17
20
 
18
21
  export type MentaAccountClient = Awaited<ReturnType<typeof createMentaAccount>>;
@@ -128,7 +128,7 @@ export type {
128
128
  AbiParameterToPrimitiveType,
129
129
  } from "abitype";
130
130
 
131
- export type { CoreClient, CoreClientConfig } from "./CoreClient";
131
+ export type { CoreClient, SmartAccountCoreClient, CoreClientConfig } from "./CoreClient";
132
132
 
133
133
  export {
134
134
  TraceFilterParameters,
@@ -0,0 +1,65 @@
1
+ import type { EIP1193RequestFn, Transport } from "viem";
2
+
3
+ /**
4
+ * RPC methods that should be routed to the bundler.
5
+ * All other methods will be routed to the public RPC.
6
+ */
7
+ const BUNDLER_METHODS = new Set([
8
+ // ERC-4337 standard methods
9
+ "eth_sendUserOperation",
10
+ "eth_estimateUserOperationGas",
11
+ "eth_getUserOperationByHash",
12
+ "eth_getUserOperationReceipt",
13
+ "eth_supportedEntryPoints",
14
+ // Pimlico-specific methods
15
+ "pimlico_getUserOperationGasPrice",
16
+ "pimlico_getUserOperationStatus",
17
+ "pimlico_sendCompressedUserOperation",
18
+ // pm_ paymaster methods (used by some bundlers)
19
+ "pm_getPaymasterData",
20
+ "pm_getPaymasterStubData",
21
+ "pm_sponsorUserOperation",
22
+ "pm_validateSponsorshipPolicies",
23
+ ]);
24
+
25
+ /**
26
+ * Creates a transport that routes requests between a public RPC and a bundler RPC.
27
+ *
28
+ * Bundler-specific methods (ERC-4337) are routed to the bundler transport,
29
+ * while all other methods (eth_getBlockByNumber, eth_call, etc.) are routed
30
+ * to the public transport.
31
+ *
32
+ * @param publicTransport - Transport for standard Ethereum RPC calls
33
+ * @param bundlerTransport - Transport for ERC-4337 bundler calls
34
+ * @returns A unified transport that routes requests appropriately
35
+ *
36
+ * @example
37
+ * import { http } from 'viem';
38
+ * import { createRoutedTransport } from '@mentaproject/core/utils';
39
+ *
40
+ * const transport = createRoutedTransport(
41
+ * http('https://eth-mainnet.g.alchemy.com/v2/...'),
42
+ * http('https://api.pimlico.io/v2/1/rpc?apikey=...')
43
+ * );
44
+ */
45
+ export function createRoutedTransport(
46
+ publicTransport: Transport,
47
+ bundlerTransport: Transport,
48
+ ): Transport {
49
+ return (params) => {
50
+ const publicClient = publicTransport(params);
51
+ const bundlerClient = bundlerTransport(params);
52
+
53
+ const request: EIP1193RequestFn = async ({ method, params: reqParams }) => {
54
+ if (BUNDLER_METHODS.has(method)) {
55
+ return bundlerClient.request({ method, params: reqParams } as any);
56
+ }
57
+ return publicClient.request({ method, params: reqParams } as any);
58
+ };
59
+
60
+ return {
61
+ ...publicClient,
62
+ request,
63
+ };
64
+ };
65
+ }
@@ -1,3 +1,4 @@
1
1
  export * from 'viem/utils';
2
2
  export { bytesToAddress, bytes32ToAddress } from './bytesToAddress';
3
- export { nonZeroAddress } from './nonZeroAddress';
3
+ export { nonZeroAddress } from './nonZeroAddress';
4
+ export { createRoutedTransport } from './createRoutedTransport';