@coinbase/cdp-sdk 1.4.0 → 1.6.0

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.
Files changed (121) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +123 -2
  3. package/_cjs/accounts/evm/toEvmServerAccount.js +26 -0
  4. package/_cjs/accounts/evm/toEvmServerAccount.js.map +1 -1
  5. package/_cjs/accounts/evm/toEvmSmartAccount.js +35 -2
  6. package/_cjs/accounts/evm/toEvmSmartAccount.js.map +1 -1
  7. package/_cjs/actions/evm/listTokenBalances.js +33 -0
  8. package/_cjs/actions/evm/listTokenBalances.js.map +1 -0
  9. package/_cjs/actions/evm/requestFaucet.js +18 -0
  10. package/_cjs/actions/evm/requestFaucet.js.map +1 -0
  11. package/_cjs/actions/evm/sendTransaction.js +29 -0
  12. package/_cjs/actions/evm/sendTransaction.js.map +1 -0
  13. package/_cjs/actions/evm/sendUserOperation.js +5 -6
  14. package/_cjs/actions/evm/sendUserOperation.js.map +1 -1
  15. package/_cjs/actions/evm/transfer/accountTransferStrategy.js +72 -0
  16. package/_cjs/actions/evm/transfer/accountTransferStrategy.js.map +1 -0
  17. package/_cjs/actions/evm/transfer/smartAccountTransferStrategy.js +67 -0
  18. package/_cjs/actions/evm/transfer/smartAccountTransferStrategy.js.map +1 -0
  19. package/_cjs/actions/evm/transfer/transfer.js +59 -0
  20. package/_cjs/actions/evm/transfer/transfer.js.map +1 -0
  21. package/_cjs/actions/evm/transfer/types.js +3 -0
  22. package/_cjs/actions/evm/transfer/types.js.map +1 -0
  23. package/_cjs/actions/evm/transfer/utils.js +39 -0
  24. package/_cjs/actions/evm/transfer/utils.js.map +1 -0
  25. package/_cjs/actions/evm/types.js +3 -0
  26. package/_cjs/actions/evm/types.js.map +1 -0
  27. package/_cjs/client/evm/evm.js +52 -42
  28. package/_cjs/client/evm/evm.js.map +1 -1
  29. package/_cjs/client/solana/solana.js +42 -0
  30. package/_cjs/client/solana/solana.js.map +1 -1
  31. package/_cjs/utils/serializeTransaction.js +18 -0
  32. package/_cjs/utils/serializeTransaction.js.map +1 -0
  33. package/_cjs/version.js +1 -1
  34. package/_esm/accounts/evm/toEvmServerAccount.js +26 -0
  35. package/_esm/accounts/evm/toEvmServerAccount.js.map +1 -1
  36. package/_esm/accounts/evm/toEvmSmartAccount.js +35 -2
  37. package/_esm/accounts/evm/toEvmSmartAccount.js.map +1 -1
  38. package/_esm/actions/evm/listTokenBalances.js +30 -0
  39. package/_esm/actions/evm/listTokenBalances.js.map +1 -0
  40. package/_esm/actions/evm/requestFaucet.js +15 -0
  41. package/_esm/actions/evm/requestFaucet.js.map +1 -0
  42. package/_esm/actions/evm/sendTransaction.js +26 -0
  43. package/_esm/actions/evm/sendTransaction.js.map +1 -0
  44. package/_esm/actions/evm/sendUserOperation.js +5 -6
  45. package/_esm/actions/evm/sendUserOperation.js.map +1 -1
  46. package/_esm/actions/evm/transfer/accountTransferStrategy.js +69 -0
  47. package/_esm/actions/evm/transfer/accountTransferStrategy.js.map +1 -0
  48. package/_esm/actions/evm/transfer/smartAccountTransferStrategy.js +64 -0
  49. package/_esm/actions/evm/transfer/smartAccountTransferStrategy.js.map +1 -0
  50. package/_esm/actions/evm/transfer/transfer.js +56 -0
  51. package/_esm/actions/evm/transfer/transfer.js.map +1 -0
  52. package/_esm/actions/evm/transfer/types.js +2 -0
  53. package/_esm/actions/evm/transfer/types.js.map +1 -0
  54. package/_esm/actions/evm/transfer/utils.js +35 -0
  55. package/_esm/actions/evm/transfer/utils.js.map +1 -0
  56. package/_esm/actions/evm/types.js +2 -0
  57. package/_esm/actions/evm/types.js.map +1 -0
  58. package/_esm/client/evm/evm.js +52 -42
  59. package/_esm/client/evm/evm.js.map +1 -1
  60. package/_esm/client/solana/solana.js +42 -0
  61. package/_esm/client/solana/solana.js.map +1 -1
  62. package/_esm/utils/serializeTransaction.js +15 -0
  63. package/_esm/utils/serializeTransaction.js.map +1 -0
  64. package/_esm/version.js +1 -1
  65. package/_types/accounts/evm/toEvmServerAccount.d.ts +2 -2
  66. package/_types/accounts/evm/toEvmServerAccount.d.ts.map +1 -1
  67. package/_types/accounts/evm/toEvmSmartAccount.d.ts +4 -4
  68. package/_types/accounts/evm/toEvmSmartAccount.d.ts.map +1 -1
  69. package/_types/accounts/types.d.ts +4 -3
  70. package/_types/accounts/types.d.ts.map +1 -1
  71. package/_types/actions/evm/listTokenBalances.d.ts +76 -0
  72. package/_types/actions/evm/listTokenBalances.d.ts.map +1 -0
  73. package/_types/actions/evm/requestFaucet.d.ts +34 -0
  74. package/_types/actions/evm/requestFaucet.d.ts.map +1 -0
  75. package/_types/actions/evm/sendTransaction.d.ts +42 -0
  76. package/_types/actions/evm/sendTransaction.d.ts.map +1 -0
  77. package/_types/actions/evm/sendUserOperation.d.ts +3 -2
  78. package/_types/actions/evm/sendUserOperation.d.ts.map +1 -1
  79. package/_types/actions/evm/transfer/accountTransferStrategy.d.ts +4 -0
  80. package/_types/actions/evm/transfer/accountTransferStrategy.d.ts.map +1 -0
  81. package/_types/actions/evm/transfer/smartAccountTransferStrategy.d.ts +4 -0
  82. package/_types/actions/evm/transfer/smartAccountTransferStrategy.d.ts.map +1 -0
  83. package/_types/actions/evm/transfer/transfer.d.ts +14 -0
  84. package/_types/actions/evm/transfer/transfer.d.ts.map +1 -0
  85. package/_types/actions/evm/transfer/types.d.ts +71 -0
  86. package/_types/actions/evm/transfer/types.d.ts.map +1 -0
  87. package/_types/actions/evm/transfer/utils.d.ts +631 -0
  88. package/_types/actions/evm/transfer/utils.d.ts.map +1 -0
  89. package/_types/actions/evm/types.d.ts +230 -0
  90. package/_types/actions/evm/types.d.ts.map +1 -0
  91. package/_types/client/evm/evm.d.ts +22 -3
  92. package/_types/client/evm/evm.d.ts.map +1 -1
  93. package/_types/client/evm/evm.types.d.ts +20 -137
  94. package/_types/client/evm/evm.types.d.ts.map +1 -1
  95. package/_types/client/solana/solana.d.ts +17 -1
  96. package/_types/client/solana/solana.d.ts.map +1 -1
  97. package/_types/client/solana/solana.types.d.ts +8 -0
  98. package/_types/client/solana/solana.types.d.ts.map +1 -1
  99. package/_types/utils/serializeTransaction.d.ts +9 -0
  100. package/_types/utils/serializeTransaction.d.ts.map +1 -0
  101. package/_types/version.d.ts +1 -1
  102. package/accounts/evm/toEvmServerAccount.ts +46 -6
  103. package/accounts/evm/toEvmSmartAccount.ts +68 -4
  104. package/accounts/types.ts +20 -16
  105. package/actions/evm/listTokenBalances.ts +107 -0
  106. package/actions/evm/requestFaucet.ts +46 -0
  107. package/actions/evm/sendTransaction.ts +73 -0
  108. package/actions/evm/sendUserOperation.ts +6 -6
  109. package/actions/evm/transfer/accountTransferStrategy.ts +84 -0
  110. package/actions/evm/transfer/smartAccountTransferStrategy.ts +72 -0
  111. package/actions/evm/transfer/transfer.ts +71 -0
  112. package/actions/evm/transfer/types.ts +81 -0
  113. package/actions/evm/transfer/utils.ts +39 -0
  114. package/actions/evm/types.ts +244 -0
  115. package/client/evm/evm.ts +70 -63
  116. package/client/evm/evm.types.ts +32 -149
  117. package/client/solana/solana.ts +43 -0
  118. package/client/solana/solana.types.ts +9 -0
  119. package/package.json +1 -1
  120. package/utils/serializeTransaction.ts +17 -0
  121. package/version.ts +1 -1
@@ -0,0 +1,71 @@
1
+ import { createPublicClient, http, erc20Abi, parseUnits, Address, Chain, Transport } from "viem";
2
+
3
+ import { TransferResult, TransferOptions, TransferExecutionStrategy } from "./types.js";
4
+ import { mapNetworkToChain } from "./utils.js";
5
+ import { EvmAccount, EvmSmartAccount } from "../../../accounts/types.js";
6
+ import { CdpOpenApiClientType } from "../../../openapi-client/index.js";
7
+
8
+ /**
9
+ * Transfer an amount of a token from an account to another account.
10
+ *
11
+ * @param apiClient - The client to use to send the transaction.
12
+ * @param from - The account to send the transaction from.
13
+ * @param transferArgs - The options for the transfer.
14
+ * @param transferStrategy - The strategy to use to execute the transfer.
15
+ * @returns The result of the transfer.
16
+ */
17
+ export async function transfer<T extends EvmAccount | EvmSmartAccount>(
18
+ apiClient: CdpOpenApiClientType,
19
+ from: T,
20
+ transferArgs: TransferOptions,
21
+ transferStrategy: TransferExecutionStrategy<T>,
22
+ ): Promise<TransferResult> {
23
+ const publicClient = createPublicClient<Transport, Chain>({
24
+ chain: mapNetworkToChain(transferArgs.network),
25
+ transport: http(),
26
+ });
27
+
28
+ const to =
29
+ typeof transferArgs.to === "string" ? transferArgs.to : (transferArgs.to.address as Address);
30
+
31
+ const value = await (async () => {
32
+ // user supplied a bigint. otherwise, we need to convert the amount to a bigint
33
+ if (typeof transferArgs.amount !== "string") {
34
+ return transferArgs.amount;
35
+ }
36
+
37
+ const decimals = await (async () => {
38
+ if (transferArgs.token === "eth") {
39
+ return 18;
40
+ } else if (transferArgs.token === "usdc") {
41
+ return 6;
42
+ } else {
43
+ return publicClient.readContract({
44
+ address: transferArgs.token,
45
+ abi: erc20Abi,
46
+ functionName: "decimals",
47
+ args: [],
48
+ });
49
+ }
50
+ })();
51
+
52
+ return parseUnits(transferArgs.amount, decimals);
53
+ })();
54
+
55
+ const hash = await transferStrategy.executeTransfer({
56
+ apiClient,
57
+ from,
58
+ transferArgs,
59
+ to,
60
+ value,
61
+ });
62
+
63
+ const result = await transferStrategy.waitForResult({
64
+ apiClient,
65
+ publicClient,
66
+ from,
67
+ hash,
68
+ });
69
+
70
+ return result;
71
+ }
@@ -0,0 +1,81 @@
1
+ import { Hex, TransactionReceipt, Address, PublicClient, Chain, Transport } from "viem";
2
+
3
+ import {
4
+ CdpOpenApiClientType,
5
+ EvmAccount,
6
+ EvmUserOperationNetwork,
7
+ SendEvmTransactionBodyNetwork,
8
+ } from "../../../openapi-client/index.js";
9
+
10
+ /**
11
+ * The network to transfer the token on.
12
+ */
13
+ export type Network = SendEvmTransactionBodyNetwork | EvmUserOperationNetwork;
14
+
15
+ /**
16
+ * The options for the transfer.
17
+ */
18
+ export type TransferOptions = {
19
+ /** The account to transfer the token to. */
20
+ to: EvmAccount | Address;
21
+ /**
22
+ * The amount of the token to transfer.
23
+ * If a string is provided, it will be parsed into a bigint based on the token's decimals.
24
+ */
25
+ amount: bigint | string;
26
+ /** The token to transfer. Can be a contract address or a predefined token name. */
27
+ token: "eth" | "usdc" | Hex;
28
+ /** The network to transfer the token on. */
29
+ network: Network;
30
+ };
31
+
32
+ /**
33
+ * The result of the transfer.
34
+ */
35
+ export type TransferResult = {
36
+ /** The status of the transaction. */
37
+ status: TransactionReceipt["status"];
38
+ /** The transaction hash of the transfer. */
39
+ transactionHash: Hex;
40
+ };
41
+
42
+ /**
43
+ * A strategy for executing a transfer.
44
+ */
45
+ export interface TransferExecutionStrategy<T> {
46
+ /**
47
+ * Executes the transfer.
48
+ *
49
+ * @param args - The arguments for the transfer.
50
+ * @param args.apiClient - The API client to use for the transfer.
51
+ * @param args.from - The account to transfer the token from.
52
+ * @param args.transferArgs - The arguments for the transfer.
53
+ * @param args.to - The account to transfer the token to.
54
+ * @param args.value - The value of the transfer.
55
+ * @returns The transaction hash of the transfer.
56
+ */
57
+ executeTransfer(args: {
58
+ apiClient: CdpOpenApiClientType;
59
+ from: T;
60
+ transferArgs: TransferOptions;
61
+ to: Address;
62
+ value: bigint;
63
+ }): Promise<Hex>;
64
+
65
+ /**
66
+ * Waits for the result of the transfer.
67
+ *
68
+ * @param args - The arguments for the transfer.
69
+ * @param args.apiClient - The API client to use for the transfer.
70
+ * @param args.publicClient - The public client to use for the transfer.
71
+ * @param args.from - The account to transfer the token from.
72
+ * @param args.hash - The transaction hash of the transfer.
73
+ * @returns The result of the transfer.
74
+ */
75
+ waitForResult(args: {
76
+ apiClient: CdpOpenApiClientType;
77
+ publicClient: PublicClient<Transport, Chain>;
78
+ from: T;
79
+ hash: Hex;
80
+ }): Promise<TransferResult>;
81
+ }
@@ -0,0 +1,39 @@
1
+ import { base, baseSepolia } from "viem/chains";
2
+
3
+ import { Network } from "./types.js";
4
+
5
+ /**
6
+ * The address of an ERC20 token for a given network.
7
+ */
8
+ const addressMap = {
9
+ base: {
10
+ usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
11
+ },
12
+ "base-sepolia": {
13
+ usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
14
+ },
15
+ };
16
+
17
+ /**
18
+ * Get the address of an ERC20 token for a given network.
19
+ * If a contract address is provided, it will not be found in the map and will be returned as is.
20
+ *
21
+ * @param token - The token symbol or contract address.
22
+ * @param network - The network to get the address for.
23
+ *
24
+ * @returns The address of the ERC20 token.
25
+ */
26
+ export function getErc20Address(token: string, network: Network) {
27
+ return addressMap[network][token] ?? token;
28
+ }
29
+
30
+ /**
31
+ * Map a network to a viem chain.
32
+ * TODO: Add more networks (or dynamically map viem chains).
33
+ *
34
+ * @param network - The network to map to a chain.
35
+ * @returns The chain for the given network.
36
+ */
37
+ export function mapNetworkToChain(network: Network) {
38
+ return network === "base" ? base : baseSepolia;
39
+ }
@@ -0,0 +1,244 @@
1
+ import { SendUserOperationReturnType, SendUserOperationOptions } from "./sendUserOperation.js";
2
+
3
+ import type { ListTokenBalancesResult, ListTokenBalancesOptions } from "./listTokenBalances.js";
4
+ import type { RequestFaucetOptions, RequestFaucetResult } from "./requestFaucet.js";
5
+ import type { SendTransactionOptions, TransactionResult } from "./sendTransaction.js";
6
+ import type { TransferOptions, TransferResult } from "./transfer/types.js";
7
+ import type {
8
+ WaitForUserOperationOptions,
9
+ WaitForUserOperationReturnType,
10
+ } from "./waitForUserOperation.js";
11
+ export type Actions = {
12
+ /**
13
+ * Transfer an amount of a token from an account to another account.
14
+ *
15
+ * @param options - The options for the transfer.
16
+ * @param options.to - The account or 0x-prefixed address to transfer the token to.
17
+ * @param options.amount - The amount of the token to transfer.
18
+ * @param options.token - The token to transfer.
19
+ * @param options.network - The network to transfer the token on.
20
+ *
21
+ * @returns The result of the transfer.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const { status } = await sender.transfer({
26
+ * to: "0x9F663335Cd6Ad02a37B633602E98866CF944124d",
27
+ * amount: "0.01",
28
+ * token: "usdc",
29
+ * network: "base-sepolia",
30
+ * });
31
+ * ```
32
+ *
33
+ * @example
34
+ * **Pass a bigint value**
35
+ * ```typescript
36
+ * const { status } = await sender.transfer({
37
+ * to: "0x9F663335Cd6Ad02a37B633602E98866CF944124d",
38
+ * amount: 10000n, // equivalent to 0.01 usdc
39
+ * token: "usdc",
40
+ * network: "base-sepolia",
41
+ * });
42
+ * ```
43
+ *
44
+ * @example
45
+ * **Transfer from a smart account**
46
+ * ```typescript
47
+ * const sender = await cdp.evm.createSmartAccount({
48
+ * owner: await cdp.evm.createAccount({ name: "Owner" }),
49
+ * });
50
+ *
51
+ * const { status } = await sender.transfer({
52
+ * to: "0x9F663335Cd6Ad02a37B633602E98866CF944124d",
53
+ * amount: "0.01",
54
+ * token: "usdc",
55
+ * network: "base-sepolia",
56
+ * });
57
+ * ```
58
+ *
59
+ * @example
60
+ * **Transfer ETH**
61
+ * ```typescript
62
+ * const { status } = await sender.transfer({
63
+ * to: "0x9F663335Cd6Ad02a37B633602E98866CF944124d",
64
+ * amount: "0.000001",
65
+ * token: "eth",
66
+ * network: "base-sepolia",
67
+ * });
68
+ * ```
69
+ *
70
+ * @example
71
+ * **Using a contract address**
72
+ * ```typescript
73
+ * const { status } = await sender.transfer({
74
+ * to: "0x9F663335Cd6Ad02a37B633602E98866CF944124d",
75
+ * amount: "0.000001",
76
+ * token: "0x4200000000000000000000000000000000000006", // WETH on Base Sepolia
77
+ * network: "base-sepolia",
78
+ * });
79
+ * ```
80
+ *
81
+ * @example
82
+ * **Transfer to another account**
83
+ * ```typescript
84
+ * const sender = await cdp.evm.createAccount({ name: "Sender" });
85
+ * const receiver = await cdp.evm.createAccount({ name: "Receiver" });
86
+ *
87
+ * const { status } = await sender.transfer({
88
+ * to: receiver,
89
+ * amount: "0.01",
90
+ * token: "usdc",
91
+ * network: "base-sepolia",
92
+ * });
93
+ * ```
94
+ */
95
+ transfer: (options: TransferOptions) => Promise<TransferResult>;
96
+
97
+ /**
98
+ * List the token balances of an account.
99
+ *
100
+ * @param options - The options for the list token balances.
101
+ * @param options.network - The network to list the token balances on.
102
+ *
103
+ * @returns The result of the list token balances.
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * const balances = await account.listTokenBalances({
108
+ * network: "base-sepolia",
109
+ * });
110
+ * ```
111
+ */
112
+ listTokenBalances: (
113
+ options: Omit<ListTokenBalancesOptions, "address">,
114
+ ) => Promise<ListTokenBalancesResult>;
115
+
116
+ /**
117
+ * Requests funds from an EVM faucet.
118
+ *
119
+ * @param {RequestFaucetOptions} options - Parameters for requesting funds from the EVM faucet.
120
+ * @param {string} options.network - The network to request funds from.
121
+ * @param {string} options.token - The token to request funds for.
122
+ * @param {string} [options.idempotencyKey] - An idempotency key.
123
+ *
124
+ * @returns A promise that resolves to the transaction hash.
125
+ *
126
+ * @example
127
+ * ```ts
128
+ * const result = await account.requestFaucet({
129
+ * network: "base-sepolia",
130
+ * token: "eth",
131
+ * });
132
+ * ```
133
+ */
134
+ requestFaucet: (options: Omit<RequestFaucetOptions, "address">) => Promise<RequestFaucetResult>;
135
+
136
+ /**
137
+ * Signs an EVM transaction and sends it to the specified network using the Coinbase API.
138
+ * This method handles nonce management and gas estimation automatically.
139
+ *
140
+ * @param {SendTransactionOptions} options - Configuration options for sending the transaction.
141
+ * @returns A promise that resolves to the transaction hash.
142
+ *
143
+ * @example
144
+ * **Sending an RLP-encoded transaction**
145
+ * ```ts
146
+ * import { parseEther, serializeTransaction } from "viem";
147
+ * import { baseSepolia } from "viem/chains";
148
+ *
149
+ * const { transactionHash } = await account.sendTransaction({
150
+ * transaction: serializeTransaction({
151
+ * to: "0x4252e0c9A3da5A2700e7d91cb50aEf522D0C6Fe8",
152
+ * value: parseEther("0.000001"),
153
+ * chainId: baseSepolia.id,
154
+ * // Fields below are optional, CDP API will populate them if omitted.
155
+ * // nonce
156
+ * // maxPriorityFeePerGas
157
+ * // maxFeePerGas
158
+ * // gas
159
+ * }),
160
+ * network: "base-sepolia",
161
+ * });
162
+ * ```
163
+ * @example
164
+ * **Sending an EIP-1559 transaction request object**
165
+ * ```ts
166
+ * const { transactionHash } = await account.sendTransaction({
167
+ * transaction: {
168
+ * to: "0x4252e0c9A3da5A2700e7d91cb50aEf522D0C6Fe8",
169
+ * value: parseEther("0.000001"),
170
+ * // Fields below are optional, CDP API will populate them if omitted.
171
+ * // nonce
172
+ * // maxPriorityFeePerGas
173
+ * // maxFeePerGas
174
+ * // gas
175
+ * },
176
+ * network: "base-sepolia",
177
+ * });
178
+ * ```
179
+ */
180
+ sendTransaction: (options: Omit<SendTransactionOptions, "address">) => Promise<TransactionResult>;
181
+
182
+ /**
183
+ * Sends a user operation.
184
+ *
185
+ * @param {SendUserOperationOptions} options - Parameters for sending the user operation.
186
+ * @param {string} options.network - The network to send the user operation on.
187
+ * @param {EvmCall[]} options.calls - The calls to include in the user operation.
188
+ * @param {string} [options.paymasterUrl] - The optional paymaster URL to use for the user operation.
189
+ * @param {string} [options.idempotencyKey] - An idempotency key.
190
+ *
191
+ * @returns A promise that resolves to an object containing the smart account address,
192
+ * the user operation hash, and the status of the user operation.
193
+ *
194
+ * @example
195
+ * ```ts
196
+ * const userOp = await smartAccount.sendUserOperation({
197
+ * network: "base-sepolia",
198
+ * calls: [
199
+ * {
200
+ * to: "0x1234567890123456789012345678901234567890",
201
+ * value: parseEther("0.000001"),
202
+ * data: "0x",
203
+ * },
204
+ * ],
205
+ * });
206
+ * ```
207
+ */
208
+ sendUserOperation: (
209
+ options: Omit<SendUserOperationOptions<unknown[]>, "smartAccount">,
210
+ ) => Promise<SendUserOperationReturnType>;
211
+
212
+ /**
213
+ * Waits for a user operation to complete or fail.
214
+ *
215
+ * @param {WaitForUserOperationOptions} options - Parameters for waiting for the user operation.
216
+ * @param {string} options.userOpHash - The user operation hash.
217
+ * @param {WaitOptions} [options.waitOptions] - Optional parameters for the wait operation.
218
+ *
219
+ * @returns A promise that resolves to the transaction receipt.
220
+ *
221
+ * @example
222
+ * ```ts
223
+ * // Send a user operation and get the user operation hash
224
+ * const { userOpHash } = await smartAccount.sendUserOperation({
225
+ * network: "base-sepolia",
226
+ * calls: [
227
+ * {
228
+ * to: "0x0000000000000000000000000000000000000000",
229
+ * value: parseEther("0.000001"),
230
+ * data: "0x",
231
+ * },
232
+ * ],
233
+ * });
234
+ *
235
+ * // Wait for the user operation to complete or fail
236
+ * const result = await smartAccount.waitForUserOperation({
237
+ * userOpHash: userOp.userOpHash,
238
+ * });
239
+ * ```
240
+ */
241
+ waitForUserOperation: (
242
+ options: Omit<WaitForUserOperationOptions, "smartAccountAddress">,
243
+ ) => Promise<WaitForUserOperationReturnType>;
244
+ };
package/client/evm/evm.ts CHANGED
@@ -1,14 +1,11 @@
1
- import { Address, serializeTransaction } from "viem";
1
+ import { Address } from "viem";
2
2
 
3
3
  import {
4
4
  CreateServerAccountOptions,
5
5
  GetServerAccountOptions,
6
6
  ListServerAccountsOptions,
7
7
  CreateSmartAccountOptions,
8
- RequestFaucetOptions,
9
- SendUserOperationOptions,
10
8
  WaitForUserOperationOptions,
11
- RequestFaucetResult,
12
9
  SignHashOptions,
13
10
  SignatureResult,
14
11
  SignMessageOptions,
@@ -23,24 +20,38 @@ import {
23
20
  GetUserOperationOptions,
24
21
  ListSmartAccountResult,
25
22
  ListSmartAccountsOptions,
26
- ListTokenBalancesOptions,
27
- ListTokenBalancesResult,
28
- SendTransactionOptions,
29
- TransactionResult,
23
+ GetOrCreateServerAccountOptions,
30
24
  } from "./evm.types.js";
31
25
  import { toEvmServerAccount } from "../../accounts/evm/toEvmServerAccount.js";
32
26
  import { toEvmSmartAccount } from "../../accounts/evm/toEvmSmartAccount.js";
27
+ import {
28
+ listTokenBalances,
29
+ ListTokenBalancesResult,
30
+ ListTokenBalancesOptions,
31
+ } from "../../actions/evm/listTokenBalances.js";
32
+ import {
33
+ RequestFaucetOptions,
34
+ RequestFaucetResult,
35
+ requestFaucet,
36
+ } from "../../actions/evm/requestFaucet.js";
37
+ import { sendTransaction } from "../../actions/evm/sendTransaction.js";
33
38
  import {
34
39
  sendUserOperation,
40
+ SendUserOperationOptions,
35
41
  SendUserOperationReturnType,
36
42
  } from "../../actions/evm/sendUserOperation.js";
37
43
  import {
38
44
  waitForUserOperation,
39
45
  WaitForUserOperationReturnType,
40
46
  } from "../../actions/evm/waitForUserOperation.js";
47
+ import { APIError } from "../../openapi-client/errors.js";
41
48
  import { CdpOpenApiClient } from "../../openapi-client/index.js";
42
49
  import { Hex } from "../../types/misc.js";
43
50
 
51
+ import type {
52
+ TransactionResult,
53
+ SendTransactionOptions,
54
+ } from "../../actions/evm/sendTransaction.js";
44
55
  /**
45
56
  * The namespace containing all EVM methods.
46
57
  */
@@ -145,7 +156,7 @@ export class EvmClient implements EvmClientInterface {
145
156
  options.idempotencyKey,
146
157
  );
147
158
 
148
- return toEvmSmartAccount({
159
+ return toEvmSmartAccount(CdpOpenApiClient, {
149
160
  smartAccount,
150
161
  owner: options.owner,
151
162
  });
@@ -216,12 +227,53 @@ export class EvmClient implements EvmClientInterface {
216
227
  async getSmartAccount(options: GetSmartAccountOptions): Promise<SmartAccount> {
217
228
  const smartAccount = await CdpOpenApiClient.getEvmSmartAccount(options.address);
218
229
 
219
- return toEvmSmartAccount({
230
+ return toEvmSmartAccount(CdpOpenApiClient, {
220
231
  smartAccount,
221
232
  owner: options.owner,
222
233
  });
223
234
  }
224
235
 
236
+ /**
237
+ * Gets a CDP EVM account, or creates one if it doesn't exist.
238
+ *
239
+ * @param {GetOrCreateServerAccountOptions} options - Parameters for getting or creating the account.
240
+ * @param {string} [options.name] - The name of the account to get or create.
241
+ *
242
+ * @returns A promise that resolves to the account.
243
+ *
244
+ * @example
245
+ * ```ts
246
+ * const account = await cdp.evm.getOrCreateAccount({
247
+ * name: "MyAccount",
248
+ * });
249
+ * ```
250
+ */
251
+ async getOrCreateAccount(options: GetOrCreateServerAccountOptions): Promise<ServerAccount> {
252
+ try {
253
+ const account = await this.getAccount(options);
254
+ return account;
255
+ } catch (error) {
256
+ // If it failed because the account doesn't exist, create it
257
+ const doesAccountNotExist = error instanceof APIError && error.statusCode === 404;
258
+ if (doesAccountNotExist) {
259
+ try {
260
+ const account = await this.createAccount(options);
261
+ return account;
262
+ } catch (error) {
263
+ // If it failed because the account already exists, throw an error
264
+ const doesAccountAlreadyExist = error instanceof APIError && error.statusCode === 409;
265
+ if (doesAccountAlreadyExist) {
266
+ const account = await this.getAccount(options);
267
+ return account;
268
+ }
269
+ throw error;
270
+ }
271
+ }
272
+
273
+ throw error;
274
+ }
275
+ }
276
+
225
277
  /**
226
278
  * Gets a user operation for a smart account by user operation hash.
227
279
  *
@@ -333,28 +385,7 @@ export class EvmClient implements EvmClientInterface {
333
385
  * }
334
386
  */
335
387
  async listTokenBalances(options: ListTokenBalancesOptions): Promise<ListTokenBalancesResult> {
336
- const response = await CdpOpenApiClient.listEvmTokenBalances(options.network, options.address, {
337
- pageSize: options.pageSize,
338
- pageToken: options.pageToken,
339
- });
340
-
341
- const balances = response.balances.map(balance => {
342
- return {
343
- token: {
344
- network: balance.token.network,
345
- contractAddress: balance.token.contractAddress as Address,
346
- },
347
- amount: {
348
- amount: BigInt(balance.amount.amount),
349
- decimals: BigInt(balance.amount.decimals),
350
- },
351
- };
352
- });
353
-
354
- return {
355
- balances,
356
- nextPageToken: response.nextPageToken,
357
- };
388
+ return listTokenBalances(CdpOpenApiClient, options);
358
389
  }
359
390
 
360
391
  /**
@@ -466,14 +497,7 @@ export class EvmClient implements EvmClientInterface {
466
497
  * ```
467
498
  */
468
499
  async requestFaucet(options: RequestFaucetOptions): Promise<RequestFaucetResult> {
469
- const { transactionHash } = await CdpOpenApiClient.requestEvmFaucet(
470
- { address: options.address, network: options.network, token: options.token },
471
- options.idempotencyKey,
472
- );
473
-
474
- return {
475
- transactionHash: transactionHash as Hex,
476
- };
500
+ return requestFaucet(CdpOpenApiClient, options);
477
501
  }
478
502
 
479
503
  /**
@@ -523,27 +547,7 @@ export class EvmClient implements EvmClientInterface {
523
547
  * ```
524
548
  */
525
549
  async sendTransaction(options: SendTransactionOptions): Promise<TransactionResult> {
526
- const { address, network, idempotencyKey } = options;
527
- let transaction = options.transaction;
528
-
529
- if (typeof transaction !== "string") {
530
- transaction = serializeTransaction({
531
- ...transaction,
532
- // chainId is ignored in favor of network
533
- chainId: 1,
534
- type: "eip1559",
535
- });
536
- }
537
-
538
- const result = await CdpOpenApiClient.sendEvmTransaction(
539
- address,
540
- { transaction, network },
541
- idempotencyKey,
542
- );
543
-
544
- return {
545
- transactionHash: result.transactionHash as Hex,
546
- };
550
+ return sendTransaction(CdpOpenApiClient, options);
547
551
  }
548
552
 
549
553
  /**
@@ -574,8 +578,11 @@ export class EvmClient implements EvmClientInterface {
574
578
  * });
575
579
  * ```
576
580
  */
577
- async sendUserOperation(options: SendUserOperationOptions): Promise<SendUserOperationReturnType> {
578
- return sendUserOperation(CdpOpenApiClient, options.smartAccount, {
581
+ async sendUserOperation(
582
+ options: SendUserOperationOptions<unknown[]>,
583
+ ): Promise<SendUserOperationReturnType> {
584
+ return sendUserOperation(CdpOpenApiClient, {
585
+ smartAccount: options.smartAccount,
579
586
  network: options.network,
580
587
  calls: options.calls,
581
588
  paymasterUrl: options.paymasterUrl,