@coinbase/cdp-sdk 1.19.0 → 1.21.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 (154) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +8 -0
  3. package/_cjs/accounts/evm/chainToNetworkMapper.js +33 -0
  4. package/_cjs/accounts/evm/chainToNetworkMapper.js.map +1 -0
  5. package/_cjs/accounts/evm/getBaseNodeRpcUrl.js +38 -0
  6. package/_cjs/accounts/evm/getBaseNodeRpcUrl.js.map +1 -0
  7. package/_cjs/accounts/evm/networkCapabilities.js +91 -0
  8. package/_cjs/accounts/evm/networkCapabilities.js.map +1 -0
  9. package/_cjs/accounts/evm/resolveViemClients.js +2 -35
  10. package/_cjs/accounts/evm/resolveViemClients.js.map +1 -1
  11. package/_cjs/accounts/evm/toEvmServerAccount.js +1 -1
  12. package/_cjs/accounts/evm/toEvmServerAccount.js.map +1 -1
  13. package/_cjs/accounts/evm/toEvmSmartAccount.js +2 -2
  14. package/_cjs/accounts/evm/toEvmSmartAccount.js.map +1 -1
  15. package/_cjs/accounts/evm/toNetworkScopedEvmServerAccount.js +87 -18
  16. package/_cjs/accounts/evm/toNetworkScopedEvmServerAccount.js.map +1 -1
  17. package/_cjs/accounts/evm/toNetworkScopedEvmSmartAccount.js +126 -2
  18. package/_cjs/accounts/evm/toNetworkScopedEvmSmartAccount.js.map +1 -1
  19. package/_cjs/actions/evm/sendUserOperation.js +8 -1
  20. package/_cjs/actions/evm/sendUserOperation.js.map +1 -1
  21. package/_cjs/actions/evm/transfer/smartAccountTransferStrategy.js +3 -2
  22. package/_cjs/actions/evm/transfer/smartAccountTransferStrategy.js.map +1 -1
  23. package/_cjs/actions/evm/transfer/transfer.js +4 -0
  24. package/_cjs/actions/evm/transfer/transfer.js.map +1 -1
  25. package/_cjs/actions/evm/transfer/transferWithViem.js +53 -0
  26. package/_cjs/actions/evm/transfer/transferWithViem.js.map +1 -0
  27. package/_cjs/actions/evm/transfer/types.js +25 -0
  28. package/_cjs/actions/evm/transfer/types.js.map +1 -1
  29. package/_cjs/client/evm/evm.js +2 -2
  30. package/_cjs/client/evm/evm.js.map +1 -1
  31. package/_cjs/client/solana/solana.js +74 -0
  32. package/_cjs/client/solana/solana.js.map +1 -1
  33. package/_cjs/constants.js +18 -1
  34. package/_cjs/constants.js.map +1 -1
  35. package/_cjs/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js +2 -0
  36. package/_cjs/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js.map +1 -1
  37. package/_cjs/openapi-client/generated/index.msw.js +4 -4
  38. package/_cjs/openapi-client/generated/index.msw.js.map +1 -1
  39. package/_cjs/openapi-client/generated/solana-accounts/solana-accounts.js +10 -1
  40. package/_cjs/openapi-client/generated/solana-accounts/solana-accounts.js.map +1 -1
  41. package/_cjs/version.js +1 -1
  42. package/_esm/accounts/evm/chainToNetworkMapper.js +30 -0
  43. package/_esm/accounts/evm/chainToNetworkMapper.js.map +1 -0
  44. package/_esm/accounts/evm/getBaseNodeRpcUrl.js +35 -0
  45. package/_esm/accounts/evm/getBaseNodeRpcUrl.js.map +1 -0
  46. package/_esm/accounts/evm/networkCapabilities.js +86 -0
  47. package/_esm/accounts/evm/networkCapabilities.js.map +1 -0
  48. package/_esm/accounts/evm/resolveViemClients.js +1 -34
  49. package/_esm/accounts/evm/resolveViemClients.js.map +1 -1
  50. package/_esm/accounts/evm/toEvmServerAccount.js +1 -1
  51. package/_esm/accounts/evm/toEvmServerAccount.js.map +1 -1
  52. package/_esm/accounts/evm/toEvmSmartAccount.js +2 -2
  53. package/_esm/accounts/evm/toEvmSmartAccount.js.map +1 -1
  54. package/_esm/accounts/evm/toNetworkScopedEvmServerAccount.js +88 -19
  55. package/_esm/accounts/evm/toNetworkScopedEvmServerAccount.js.map +1 -1
  56. package/_esm/accounts/evm/toNetworkScopedEvmSmartAccount.js +126 -2
  57. package/_esm/accounts/evm/toNetworkScopedEvmSmartAccount.js.map +1 -1
  58. package/_esm/actions/evm/sendUserOperation.js +8 -1
  59. package/_esm/actions/evm/sendUserOperation.js.map +1 -1
  60. package/_esm/actions/evm/transfer/smartAccountTransferStrategy.js +3 -2
  61. package/_esm/actions/evm/transfer/smartAccountTransferStrategy.js.map +1 -1
  62. package/_esm/actions/evm/transfer/transfer.js +4 -0
  63. package/_esm/actions/evm/transfer/transfer.js.map +1 -1
  64. package/_esm/actions/evm/transfer/transferWithViem.js +50 -0
  65. package/_esm/actions/evm/transfer/transferWithViem.js.map +1 -0
  66. package/_esm/actions/evm/transfer/types.js +23 -1
  67. package/_esm/actions/evm/transfer/types.js.map +1 -1
  68. package/_esm/client/evm/evm.js +2 -2
  69. package/_esm/client/evm/evm.js.map +1 -1
  70. package/_esm/client/solana/solana.js +71 -0
  71. package/_esm/client/solana/solana.js.map +1 -1
  72. package/_esm/constants.js +17 -0
  73. package/_esm/constants.js.map +1 -1
  74. package/_esm/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js +2 -0
  75. package/_esm/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js.map +1 -1
  76. package/_esm/openapi-client/generated/index.msw.js +4 -4
  77. package/_esm/openapi-client/generated/index.msw.js.map +1 -1
  78. package/_esm/openapi-client/generated/solana-accounts/solana-accounts.js +8 -0
  79. package/_esm/openapi-client/generated/solana-accounts/solana-accounts.js.map +1 -1
  80. package/_esm/version.js +1 -1
  81. package/_types/accounts/evm/chainToNetworkMapper.d.ts +11 -0
  82. package/_types/accounts/evm/chainToNetworkMapper.d.ts.map +1 -0
  83. package/_types/accounts/evm/getBaseNodeRpcUrl.d.ts +8 -0
  84. package/_types/accounts/evm/getBaseNodeRpcUrl.d.ts.map +1 -0
  85. package/_types/accounts/evm/networkCapabilities.d.ts +103 -0
  86. package/_types/accounts/evm/networkCapabilities.d.ts.map +1 -0
  87. package/_types/accounts/evm/resolveViemClients.d.ts.map +1 -1
  88. package/_types/accounts/evm/toEvmServerAccount.d.ts.map +1 -1
  89. package/_types/accounts/evm/toEvmSmartAccount.d.ts.map +1 -1
  90. package/_types/accounts/evm/toNetworkScopedEvmServerAccount.d.ts +3 -3
  91. package/_types/accounts/evm/toNetworkScopedEvmServerAccount.d.ts.map +1 -1
  92. package/_types/accounts/evm/toNetworkScopedEvmSmartAccount.d.ts +9 -6
  93. package/_types/accounts/evm/toNetworkScopedEvmSmartAccount.d.ts.map +1 -1
  94. package/_types/accounts/evm/types.d.ts +109 -12
  95. package/_types/accounts/evm/types.d.ts.map +1 -1
  96. package/_types/actions/evm/sendUserOperation.d.ts.map +1 -1
  97. package/_types/actions/evm/swap/types.d.ts +9 -4
  98. package/_types/actions/evm/swap/types.d.ts.map +1 -1
  99. package/_types/actions/evm/transfer/smartAccountTransferStrategy.d.ts.map +1 -1
  100. package/_types/actions/evm/transfer/transfer.d.ts.map +1 -1
  101. package/_types/actions/evm/transfer/transferWithViem.d.ts +16 -0
  102. package/_types/actions/evm/transfer/transferWithViem.d.ts.map +1 -0
  103. package/_types/actions/evm/transfer/types.d.ts +17 -1
  104. package/_types/actions/evm/transfer/types.d.ts.map +1 -1
  105. package/_types/client/evm/evm.d.ts.map +1 -1
  106. package/_types/client/evm/evm.types.d.ts +1 -1
  107. package/_types/client/evm/evm.types.d.ts.map +1 -1
  108. package/_types/client/solana/solana.d.ts +40 -1
  109. package/_types/client/solana/solana.d.ts.map +1 -1
  110. package/_types/client/solana/solana.types.d.ts +15 -1
  111. package/_types/client/solana/solana.types.d.ts.map +1 -1
  112. package/_types/constants.d.ts +4 -0
  113. package/_types/constants.d.ts.map +1 -1
  114. package/_types/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.d.ts +2 -0
  115. package/_types/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.d.ts.map +1 -1
  116. package/_types/openapi-client/generated/index.msw.d.ts +4 -4
  117. package/_types/openapi-client/generated/index.msw.d.ts.map +1 -1
  118. package/_types/openapi-client/generated/solana-accounts/solana-accounts.d.ts +5 -0
  119. package/_types/openapi-client/generated/solana-accounts/solana-accounts.d.ts.map +1 -1
  120. package/_types/openapi-client/index.d.ts +10 -0
  121. package/_types/openapi-client/index.d.ts.map +1 -1
  122. package/_types/version.d.ts +1 -1
  123. package/accounts/evm/chainToNetworkMapper.ts +37 -0
  124. package/accounts/evm/getBaseNodeRpcUrl.ts +40 -0
  125. package/accounts/evm/networkCapabilities.ts +117 -0
  126. package/accounts/evm/resolveViemClients.ts +1 -38
  127. package/accounts/evm/toEvmServerAccount.ts +3 -3
  128. package/accounts/evm/toEvmSmartAccount.ts +3 -3
  129. package/accounts/evm/toNetworkScopedEvmServerAccount.ts +116 -29
  130. package/accounts/evm/toNetworkScopedEvmSmartAccount.ts +178 -11
  131. package/accounts/evm/types.ts +253 -23
  132. package/actions/evm/sendUserOperation.ts +9 -1
  133. package/actions/evm/swap/types.ts +11 -3
  134. package/actions/evm/transfer/smartAccountTransferStrategy.ts +5 -2
  135. package/actions/evm/transfer/transfer.ts +8 -0
  136. package/actions/evm/transfer/transferWithViem.ts +66 -0
  137. package/actions/evm/transfer/types.ts +31 -1
  138. package/client/evm/evm.ts +2 -2
  139. package/client/evm/evm.types.ts +1 -1
  140. package/client/solana/solana.ts +89 -0
  141. package/client/solana/solana.types.ts +16 -0
  142. package/constants.ts +18 -0
  143. package/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.ts +2 -0
  144. package/openapi-client/generated/index.msw.ts +4 -4
  145. package/openapi-client/generated/solana-accounts/solana-accounts.ts +20 -0
  146. package/package.json +1 -1
  147. package/version.ts +1 -1
  148. package/_cjs/client/evm/constants.js +0 -21
  149. package/_cjs/client/evm/constants.js.map +0 -1
  150. package/_esm/client/evm/constants.js +0 -18
  151. package/_esm/client/evm/constants.js.map +0 -1
  152. package/_types/client/evm/constants.d.ts +0 -5
  153. package/_types/client/evm/constants.d.ts.map +0 -1
  154. package/client/evm/constants.ts +0 -17
@@ -1,6 +1,50 @@
1
+ import {
2
+ ListTokenBalancesNetworks,
3
+ RequestFaucetNetworks,
4
+ QuoteFundNetworks,
5
+ FundNetworks,
6
+ TransferNetworks,
7
+ QuoteSwapNetworks,
8
+ SwapNetworks,
9
+ } from "./networkCapabilities.js";
10
+ import { FundOptions } from "../../actions/evm/fund/fund.js";
11
+ import { Quote } from "../../actions/evm/fund/Quote.js";
12
+ import { QuoteFundOptions } from "../../actions/evm/fund/quoteFund.js";
13
+ import { FundOperationResult } from "../../actions/evm/fund/types.js";
14
+ import {
15
+ WaitForFundOperationOptions,
16
+ WaitForFundOperationResult,
17
+ } from "../../actions/evm/fund/waitForFundOperationReceipt.js";
18
+ import {
19
+ ListTokenBalancesOptions,
20
+ ListTokenBalancesResult,
21
+ } from "../../actions/evm/listTokenBalances.js";
1
22
  import { RequestFaucetOptions, RequestFaucetResult } from "../../actions/evm/requestFaucet.js";
2
23
  import { TransactionResult, SendTransactionOptions } from "../../actions/evm/sendTransaction.js";
24
+ import {
25
+ SendUserOperationOptions,
26
+ SendUserOperationReturnType,
27
+ } from "../../actions/evm/sendUserOperation.js";
28
+ import {
29
+ AccountQuoteSwapOptions,
30
+ AccountQuoteSwapResult,
31
+ AccountSwapOptions,
32
+ AccountSwapResult,
33
+ SmartAccountQuoteSwapOptions,
34
+ SmartAccountQuoteSwapResult,
35
+ SmartAccountSwapOptions,
36
+ SmartAccountSwapResult,
37
+ } from "../../actions/evm/swap/types.js";
38
+ import {
39
+ WaitForUserOperationOptions,
40
+ WaitForUserOperationReturnType,
41
+ } from "../../actions/evm/waitForUserOperation.js";
42
+ import { GetUserOperationOptions, UserOperation } from "../../client/evm/evm.types.js";
3
43
 
44
+ import type {
45
+ SmartAccountTransferOptions,
46
+ TransferOptions,
47
+ } from "../../actions/evm/transfer/types.js";
4
48
  import type { AccountActions, SmartAccountActions } from "../../actions/evm/types.js";
5
49
  import type { Address, Hash, Hex } from "../../types/misc.js";
6
50
  import type { Prettify } from "../../types/utils.js";
@@ -37,6 +81,27 @@ export type EvmAccount = {
37
81
  policies?: string[];
38
82
  };
39
83
 
84
+ /**
85
+ * Known EVM networks supported by the SDK.
86
+ */
87
+ export type KnownEvmNetworks =
88
+ | "base"
89
+ | "base-sepolia"
90
+ | "ethereum"
91
+ | "ethereum-sepolia"
92
+ | "ethereum-hoodi"
93
+ | "polygon"
94
+ | "polygon-mumbai"
95
+ | "arbitrum"
96
+ | "arbitrum-sepolia"
97
+ | "optimism"
98
+ | "optimism-sepolia";
99
+
100
+ /**
101
+ * Network input that accepts known networks or RPC URLs
102
+ */
103
+ export type NetworkOrRpcUrl = KnownEvmNetworks | (string & {});
104
+
40
105
  /**
41
106
  * Server-managed ethereum account
42
107
  */
@@ -47,8 +112,23 @@ export type EvmServerAccount = Prettify<
47
112
  name?: string;
48
113
  /** Indicates this is a server-managed account. */
49
114
  type: "evm-server";
50
- /** A function that returns a network-scoped server-managed account. */
51
- useNetwork: (network: string) => Promise<NetworkScopedEvmServerAccount>;
115
+ /**
116
+ * A function that returns a network-scoped server-managed account.
117
+ *
118
+ * @param network - The network name or RPC URL
119
+ * @example
120
+ * // For known networks, type is inferred automatically:
121
+ * const baseAccount = await account.useNetwork("base");
122
+ *
123
+ * // For custom RPC URLs with type hints (requires casting):
124
+ * const typedAccount = await account.useNetwork<"base">("https://mainnet.base.org" as "base");
125
+ *
126
+ * // For custom RPC URLs without type hints (only sendTransaction and waitForTransactionReceipt methods available):
127
+ * const customAccount = await account.useNetwork("https://mainnet.base.org");
128
+ */
129
+ useNetwork: <Network extends NetworkOrRpcUrl>(
130
+ network: Network,
131
+ ) => Promise<NetworkScopedEvmServerAccount<Network>>;
52
132
  }
53
133
  >;
54
134
 
@@ -61,8 +141,23 @@ type EvmSmartAccountProperties = {
61
141
  owners: EvmAccount[];
62
142
  /** Identifier for the smart account type. */
63
143
  type: "evm-smart";
64
- /** Subject to breaking changes. A function that returns a network-scoped smart account. */
65
- __experimental_useNetwork: (network: string) => Promise<NetworkScopedEvmSmartAccount>;
144
+ /**
145
+ * A function that returns a network-scoped smart account.
146
+ *
147
+ * @param network - The network name or RPC URL
148
+ * @example
149
+ * // For known networks, type is inferred automatically:
150
+ * const baseAccount = await smartAccount.useNetwork("base");
151
+ *
152
+ * // For custom RPC URLs with type hints (requires casting):
153
+ * const typedAccount = await smartAccount.useNetwork<"base">("https://mainnet.base.org" as "base");
154
+ *
155
+ * // For custom RPC URLs without type hints (only sendTransaction, transfer and waitForTransactionReceipt methods available):
156
+ * const customAccount = await smartAccount.useNetwork("https://mainnet.base.org");
157
+ */
158
+ useNetwork: <Network extends KnownEvmNetworks>(
159
+ network: Network,
160
+ ) => Promise<NetworkScopedEvmSmartAccount<Network>>;
66
161
  };
67
162
 
68
163
  /**
@@ -70,32 +165,167 @@ type EvmSmartAccountProperties = {
70
165
  */
71
166
  export type EvmSmartAccount = Prettify<EvmSmartAccountProperties & SmartAccountActions>;
72
167
 
73
- export type NetworkScopedEvmSmartAccount = Prettify<
74
- Omit<EvmSmartAccountProperties, "__experimental_useNetwork"> & {
75
- /** The network to scope the smart account object to. */
76
- network: string;
77
- }
168
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
169
+ type DistributedOmit<T, K extends PropertyKey> = T extends any ? Omit<T, K> : never;
170
+
171
+ /**
172
+ * Helper type for network-specific smart account actions
173
+ */
174
+ type NetworkSpecificSmartAccountActions<Network extends string> = Prettify<
175
+ // Always include sendUserOperation, waitForUserOperation and getUserOperation
176
+ {
177
+ sendUserOperation: <const callData extends unknown[]>(
178
+ options: Omit<SendUserOperationOptions<callData>, "smartAccount" | "network">,
179
+ ) => Promise<SendUserOperationReturnType>;
180
+ waitForUserOperation: (
181
+ options: Omit<WaitForUserOperationOptions, "smartAccountAddress" | "network">,
182
+ ) => Promise<WaitForUserOperationReturnType>;
183
+ getUserOperation: (
184
+ options: Omit<GetUserOperationOptions, "smartAccount" | "network">,
185
+ ) => Promise<UserOperation>;
186
+ } & (Network extends TransferNetworks
187
+ ? {
188
+ transfer: (
189
+ options: Omit<SmartAccountTransferOptions, "network">,
190
+ ) => Promise<SendUserOperationReturnType>;
191
+ }
192
+ : EmptyObject) &
193
+ // Conditionally include listTokenBalances
194
+ (Network extends ListTokenBalancesNetworks
195
+ ? {
196
+ listTokenBalances: (
197
+ options: Omit<ListTokenBalancesOptions, "address" | "network">,
198
+ ) => Promise<ListTokenBalancesResult>;
199
+ }
200
+ : EmptyObject) &
201
+ // Conditionally include requestFaucet
202
+ (Network extends RequestFaucetNetworks
203
+ ? {
204
+ requestFaucet: (
205
+ options: Omit<RequestFaucetOptions, "address" | "network">,
206
+ ) => Promise<RequestFaucetResult>;
207
+ }
208
+ : EmptyObject) &
209
+ // Conditionally include quoteFund
210
+ (Network extends QuoteFundNetworks
211
+ ? {
212
+ quoteFund: (options: Omit<QuoteFundOptions, "address" | "network">) => Promise<Quote>;
213
+ }
214
+ : EmptyObject) &
215
+ // Conditionally include fund
216
+ (Network extends FundNetworks
217
+ ? {
218
+ fund: (options: Omit<FundOptions, "address" | "network">) => Promise<FundOperationResult>;
219
+ waitForFundOperationReceipt: (
220
+ options: Omit<WaitForFundOperationOptions, "network">,
221
+ ) => Promise<WaitForFundOperationResult>;
222
+ }
223
+ : EmptyObject) &
224
+ // Conditionally include quoteSwap
225
+ (Network extends QuoteSwapNetworks
226
+ ? {
227
+ quoteSwap: (
228
+ options: Omit<SmartAccountQuoteSwapOptions, "network">,
229
+ ) => Promise<SmartAccountQuoteSwapResult>;
230
+ }
231
+ : EmptyObject) &
232
+ // Conditionally include swap
233
+ (Network extends SwapNetworks
234
+ ? {
235
+ swap: (
236
+ options: DistributedOmit<SmartAccountSwapOptions, "network">,
237
+ ) => Promise<SmartAccountSwapResult>;
238
+ }
239
+ : EmptyObject)
240
+ >;
241
+
242
+ /**
243
+ * A network-scoped smart account
244
+ */
245
+ export type NetworkScopedEvmSmartAccount<Network extends string = string> = Prettify<
246
+ Omit<EvmSmartAccountProperties, "useNetwork"> &
247
+ NetworkSpecificSmartAccountActions<Network> & {
248
+ /** The network this account is scoped to */
249
+ network: Network;
250
+ }
78
251
  >;
79
252
 
80
- type NetworkScopedAccountActions = Prettify<{
81
- requestFaucet: (
82
- options: Omit<RequestFaucetOptions, "address" | "network">,
83
- ) => Promise<RequestFaucetResult>;
84
- sendTransaction: (
85
- options: Omit<SendTransactionOptions, "address" | "network">,
86
- ) => Promise<TransactionResult>;
87
- waitForTransactionReceipt: (
88
- options: WaitForTransactionReceiptParameters | TransactionResult,
89
- ) => Promise<TransactionReceipt>;
90
- }>;
253
+ /**
254
+ * Helper type to surface a TypeError when calling a method that doesn't exist based on the network
255
+ */
256
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
257
+ type EmptyObject = {};
258
+
259
+ /**
260
+ * Conditional account actions based on network
261
+ */
262
+ type NetworkSpecificAccountActions<Network extends string> = Prettify<
263
+ // Always include sendTransaction, transfer and waitForTransactionReceipt
264
+ {
265
+ sendTransaction: (
266
+ options: Omit<SendTransactionOptions, "address" | "network">,
267
+ ) => Promise<TransactionResult>;
268
+ transfer: (options: Omit<TransferOptions, "address" | "network">) => Promise<TransactionResult>;
269
+ waitForTransactionReceipt: (
270
+ options: WaitForTransactionReceiptParameters | TransactionResult,
271
+ ) => Promise<TransactionReceipt>;
272
+ } & (Network extends ListTokenBalancesNetworks // Conditionally include listTokenBalances
273
+ ? {
274
+ listTokenBalances: (
275
+ options: Omit<ListTokenBalancesOptions, "address" | "network">,
276
+ ) => Promise<ListTokenBalancesResult>;
277
+ }
278
+ : EmptyObject) &
279
+ // Conditionally include requestFaucet
280
+ (Network extends RequestFaucetNetworks
281
+ ? {
282
+ requestFaucet: (
283
+ options: Omit<RequestFaucetOptions, "address" | "network">,
284
+ ) => Promise<RequestFaucetResult>;
285
+ }
286
+ : EmptyObject) &
287
+ // Conditionally include quoteFund
288
+ (Network extends QuoteFundNetworks
289
+ ? {
290
+ quoteFund: (options: Omit<QuoteFundOptions, "address">) => Promise<Quote>;
291
+ }
292
+ : EmptyObject) &
293
+ // Conditionally include fund
294
+ (Network extends FundNetworks
295
+ ? {
296
+ fund: (options: Omit<FundOptions, "address">) => Promise<FundOperationResult>;
297
+ waitForFundOperationReceipt: (
298
+ options: WaitForFundOperationOptions,
299
+ ) => Promise<WaitForFundOperationResult>;
300
+ }
301
+ : EmptyObject) &
302
+ // Conditionally include transfer
303
+ (Network extends TransferNetworks
304
+ ? {
305
+ transfer: (options: TransferOptions) => Promise<{ transactionHash: Hex }>;
306
+ }
307
+ : EmptyObject) &
308
+ // Conditionally include quoteSwap
309
+ (Network extends QuoteSwapNetworks
310
+ ? {
311
+ quoteSwap: (options: AccountQuoteSwapOptions) => Promise<AccountQuoteSwapResult>;
312
+ }
313
+ : EmptyObject) &
314
+ // Conditionally include swap
315
+ (Network extends SwapNetworks
316
+ ? {
317
+ swap: (options: AccountSwapOptions) => Promise<AccountSwapResult>;
318
+ }
319
+ : EmptyObject)
320
+ >;
91
321
 
92
322
  /**
93
323
  * A network-scoped server-managed ethereum account
94
324
  */
95
- export type NetworkScopedEvmServerAccount = Prettify<
325
+ export type NetworkScopedEvmServerAccount<Network extends string = string> = Prettify<
96
326
  Omit<EvmServerAccount, keyof AccountActions | "useNetwork"> &
97
- NetworkScopedAccountActions & {
327
+ NetworkSpecificAccountActions<Network> & {
98
328
  /** The network this account is scoped to */
99
- network: string;
329
+ network: Network;
100
330
  }
101
331
  >;
@@ -1,5 +1,6 @@
1
1
  import { encodeFunctionData } from "viem";
2
2
 
3
+ import { getBaseNodeRpcUrl } from "../../accounts/evm/getBaseNodeRpcUrl.js";
3
4
  import {
4
5
  EvmUserOperationNetwork,
5
6
  EvmUserOperationStatus,
@@ -106,7 +107,14 @@ export async function sendUserOperation<T extends readonly unknown[]>(
106
107
  client: CdpOpenApiClientType,
107
108
  options: SendUserOperationOptions<T>,
108
109
  ): Promise<SendUserOperationReturnType> {
109
- const { calls, network, paymasterUrl } = options;
110
+ const { calls, network, paymasterUrl: _paymasterUrl } = options;
111
+
112
+ const paymasterUrl = await (async () => {
113
+ if (!_paymasterUrl && network === "base") {
114
+ return getBaseNodeRpcUrl("base");
115
+ }
116
+ return _paymasterUrl;
117
+ })();
110
118
 
111
119
  if (calls.length === 0) {
112
120
  throw new Error("Calls array is empty");
@@ -8,9 +8,13 @@ import type {
8
8
  SendEvmTransactionBodyNetwork,
9
9
  EvmUserOperationNetwork,
10
10
  EvmUserOperationStatus,
11
+ EvmSwapsNetwork,
11
12
  } from "../../../openapi-client/index.js";
12
13
  import type { Address, Hex } from "../../../types/misc.js";
13
14
 
15
+ // Type representing networks that support both user operations and swaps.
16
+ export type SmartAccountSwapNetwork = Extract<EvmSwapsNetwork, EvmUserOperationNetwork>;
17
+
14
18
  /**
15
19
  * Base options for sending a swap transaction.
16
20
  */
@@ -144,7 +148,10 @@ export type AccountSwapResult = SendSwapTransactionResult;
144
148
  /**
145
149
  * Options for creating a swap quote (smart account-level).
146
150
  */
147
- export type SmartAccountQuoteSwapOptions = Omit<CreateSwapQuoteOptions, "taker">;
151
+ export type SmartAccountQuoteSwapOptions = Omit<CreateSwapQuoteOptions, "taker" | "network"> & {
152
+ /** The network to create a swap quote on. Smart accounts only support networks that support both user operations and swaps. */
153
+ network: SmartAccountSwapNetwork;
154
+ };
148
155
 
149
156
  /**
150
157
  * Result of creating a swap quote (smart account-level).
@@ -176,9 +183,10 @@ interface SmartAccountQuoteBasedSwapOptions {
176
183
  */
177
184
  interface SmartAccountInlineSwapOptions {
178
185
  /**
179
- * The network to execute the swap on (e.g., "ethereum", "base").
186
+ * The network to execute the swap on (e.g., "base").
187
+ * Smart accounts only support networks that support both user operations and swaps.
180
188
  */
181
- network: SendEvmTransactionBodyNetwork;
189
+ network: SmartAccountSwapNetwork;
182
190
  /** The token to receive (destination token). */
183
191
  toToken: Address;
184
192
  /** The token to send (source token). */
@@ -5,14 +5,17 @@ import { sendUserOperation } from "../sendUserOperation.js";
5
5
 
6
6
  import type { TransferExecutionStrategy } from "./types.js";
7
7
  import type { EvmSmartAccount } from "../../../accounts/evm/types.js";
8
+ import type { EvmUserOperationNetwork } from "../../../openapi-client/index.js";
8
9
 
9
10
  export const smartAccountTransferStrategy: TransferExecutionStrategy<EvmSmartAccount> = {
10
11
  executeTransfer: async ({ apiClient, from, to, value, token, network, paymasterUrl }) => {
12
+ const smartAccountNetwork = network as EvmUserOperationNetwork;
13
+
11
14
  if (token === "eth") {
12
15
  const result = await sendUserOperation(apiClient, {
13
16
  smartAccount: from,
14
17
  paymasterUrl,
15
- network,
18
+ network: smartAccountNetwork,
16
19
  calls: [
17
20
  {
18
21
  to,
@@ -28,7 +31,7 @@ export const smartAccountTransferStrategy: TransferExecutionStrategy<EvmSmartAcc
28
31
  const result = await sendUserOperation(apiClient, {
29
32
  smartAccount: from,
30
33
  paymasterUrl,
31
- network,
34
+ network: smartAccountNetwork,
32
35
  calls: [
33
36
  {
34
37
  to: erc20Address,
@@ -1,3 +1,5 @@
1
+ import { isValidNetworkForAccount } from "./types.js";
2
+
1
3
  import type {
2
4
  TransferExecutionStrategy,
3
5
  SmartAccountTransferOptions,
@@ -24,6 +26,12 @@ export async function transfer<T extends EvmAccount | EvmSmartAccount>(
24
26
  transferArgs: T extends EvmSmartAccount ? SmartAccountTransferOptions : TransferOptions,
25
27
  transferStrategy: TransferExecutionStrategy<T>,
26
28
  ): Promise<T extends EvmSmartAccount ? SendUserOperationReturnType : TransactionResult> {
29
+ if (!isValidNetworkForAccount(transferArgs.network, from)) {
30
+ throw new Error(
31
+ `Network "${transferArgs.network}" is not supported for the given account type.`,
32
+ );
33
+ }
34
+
27
35
  const to =
28
36
  typeof transferArgs.to === "string" ? transferArgs.to : (transferArgs.to.address as Address);
29
37
 
@@ -0,0 +1,66 @@
1
+ import { encodeFunctionData, erc20Abi } from "viem";
2
+
3
+ import { getErc20Address } from "./utils.js";
4
+ import { mapChainToNetwork } from "../../../accounts/evm/chainToNetworkMapper.js";
5
+
6
+ import type { Network, TransferOptions } from "./types.js";
7
+ import type { EvmAccount } from "../../../accounts/evm/types.js";
8
+ import type { Hex } from "../../../types/misc.js";
9
+ import type { TransactionResult } from "../sendTransaction.js";
10
+ import type { Account, Chain, Transport, WalletClient } from "viem";
11
+
12
+ /**
13
+ * Transfer an amount of a token from a network-scoped account to another account.
14
+ * This function is used for accounts that are scoped to a specific network and use
15
+ * a wallet client for transaction execution instead of the API client.
16
+ *
17
+ * @param walletClient - The wallet client to use for transaction execution.
18
+ * @param from - The account to send the transaction from.
19
+ * @param transferArgs - The transfer options.
20
+ * @returns The result of the transfer.
21
+ */
22
+ export async function transferWithViem<T extends EvmAccount>(
23
+ walletClient: WalletClient<Transport, Chain, Account>,
24
+ from: T,
25
+ transferArgs: Omit<TransferOptions, "address" | "network">,
26
+ ): Promise<TransactionResult> {
27
+ const token = transferArgs.token;
28
+ const to = typeof transferArgs.to === "string" ? transferArgs.to : transferArgs.to.address;
29
+ const value = transferArgs.amount;
30
+
31
+ if (token === "eth") {
32
+ const hash = await walletClient.sendTransaction({
33
+ account: from.address,
34
+ to,
35
+ value,
36
+ });
37
+ return { transactionHash: hash as Hex };
38
+ }
39
+
40
+ const network = mapChainToNetwork(walletClient.chain) as Network;
41
+ const erc20Address = getErc20Address(token, network);
42
+
43
+ // First approve the transfer
44
+ await walletClient.sendTransaction({
45
+ account: from.address,
46
+ to: erc20Address,
47
+ data: encodeFunctionData({
48
+ abi: erc20Abi,
49
+ functionName: "approve",
50
+ args: [to, value],
51
+ }),
52
+ });
53
+
54
+ // Then execute the transfer
55
+ const hash = await walletClient.sendTransaction({
56
+ account: from.address,
57
+ to: erc20Address,
58
+ data: encodeFunctionData({
59
+ abi: erc20Abi,
60
+ functionName: "transfer",
61
+ args: [to, value],
62
+ }),
63
+ });
64
+
65
+ return { transactionHash: hash as Hex };
66
+ }
@@ -1,8 +1,10 @@
1
+ import { EvmUserOperationNetwork } from "../../../openapi-client/index.js";
2
+
1
3
  import type { EvmAccount, EvmSmartAccount } from "../../../accounts/evm/types.js";
2
4
  import type {
3
5
  CdpOpenApiClientType,
4
- EvmUserOperationNetwork,
5
6
  SendEvmTransactionBodyNetwork,
7
+ EvmUserOperationNetwork as EvmUserOperationNetworkType,
6
8
  } from "../../../openapi-client/index.js";
7
9
  import type { TransactionResult } from "../sendTransaction.js";
8
10
  import type { SendUserOperationReturnType } from "../sendUserOperation.js";
@@ -64,3 +66,31 @@ export interface TransferExecutionStrategy<T extends EvmAccount | EvmSmartAccoun
64
66
  } & (T extends EvmSmartAccount ? { paymasterUrl?: string } : object),
65
67
  ): Promise<T extends EvmSmartAccount ? SendUserOperationReturnType : TransactionResult>;
66
68
  }
69
+
70
+ /**
71
+ * Validates that the network is supported for the given account type.
72
+ *
73
+ * @param network - The network to validate
74
+ * @param account - The account to check network support for
75
+ * @returns true if the network is valid for the account type
76
+ */
77
+ export function isValidNetworkForAccount(
78
+ network: Network,
79
+ account: EvmAccount | EvmSmartAccount,
80
+ ): boolean {
81
+ if (isSmartAccount(account)) {
82
+ return Object.values(EvmUserOperationNetwork).includes(network as EvmUserOperationNetworkType);
83
+ }
84
+
85
+ return true;
86
+ }
87
+
88
+ /**
89
+ * Type guard to check if an account is a smart account.
90
+ *
91
+ * @param account - The account to check.
92
+ * @returns true if the account is a smart account, false otherwise.
93
+ */
94
+ export function isSmartAccount(account: EvmAccount | EvmSmartAccount): account is EvmSmartAccount {
95
+ return "type" in account && account.type === "evm-smart";
96
+ }
package/client/evm/evm.ts CHANGED
@@ -2,7 +2,6 @@ import { constants, publicEncrypt } from "crypto";
2
2
 
3
3
  import { type Address, getTypesForEIP712Domain } from "viem";
4
4
 
5
- import { ImportEvmAccountPublicRSAKey } from "./constants.js";
6
5
  import {
7
6
  CreateServerAccountOptions,
8
7
  CreateSmartAccountOptions,
@@ -61,6 +60,7 @@ import {
61
60
  WaitForUserOperationReturnType,
62
61
  } from "../../actions/evm/waitForUserOperation.js";
63
62
  import { Analytics } from "../../analytics.js";
63
+ import { ImportAccountPublicRSAKey } from "../../constants.js";
64
64
  import { APIError } from "../../openapi-client/errors.js";
65
65
  import {
66
66
  CdpOpenApiClient,
@@ -173,7 +173,7 @@ export class EvmClient implements EvmClientInterface {
173
173
  * ```
174
174
  */
175
175
  async importAccount(options: ImportServerAccountOptions): Promise<ServerAccount> {
176
- const encryptionPublicKey = options.encryptionPublicKey || ImportEvmAccountPublicRSAKey;
176
+ const encryptionPublicKey = options.encryptionPublicKey || ImportAccountPublicRSAKey;
177
177
 
178
178
  const privateKeyHex = options.privateKey.startsWith("0x")
179
179
  ? options.privateKey.slice(2)
@@ -405,7 +405,7 @@ export interface ListServerAccountsOptions {
405
405
  * A smart account that only contains the owner address.
406
406
  */
407
407
  export interface ReadonlySmartAccount
408
- extends Omit<SmartAccount, "owners" | keyof SmartAccountActions | "__experimental_useNetwork"> {
408
+ extends Omit<SmartAccount, "owners" | keyof SmartAccountActions | "useNetwork"> {
409
409
  /** The owners of the smart account. */
410
410
  owners: Address[];
411
411
  }
@@ -1,8 +1,13 @@
1
+ import { constants, publicEncrypt } from "crypto";
2
+
3
+ import bs58 from "bs58";
4
+
1
5
  import {
2
6
  CreateAccountOptions,
3
7
  ExportAccountOptions,
4
8
  GetAccountOptions,
5
9
  GetOrCreateAccountOptions,
10
+ ImportAccountOptions,
6
11
  ListAccountsOptions,
7
12
  ListAccountsResult,
8
13
  RequestFaucetOptions,
@@ -18,6 +23,7 @@ import { requestFaucet } from "../../actions/solana/requestFaucet.js";
18
23
  import { signMessage } from "../../actions/solana/signMessage.js";
19
24
  import { signTransaction } from "../../actions/solana/signTransaction.js";
20
25
  import { Analytics } from "../../analytics.js";
26
+ import { ImportAccountPublicRSAKey } from "../../constants.js";
21
27
  import { APIError } from "../../openapi-client/errors.js";
22
28
  import { CdpOpenApiClient } from "../../openapi-client/index.js";
23
29
  import {
@@ -133,6 +139,89 @@ export class SolanaClient implements SolanaClientInterface {
133
139
  return formatSolanaPrivateKey(decryptedPrivateKey);
134
140
  }
135
141
 
142
+ /**
143
+ * Imports a Solana account using a private key.
144
+ * The private key will be encrypted before being stored securely.
145
+ *
146
+ * @param {ImportAccountOptions} options - Parameters for importing the Solana account.
147
+ * @param {string} options.privateKey - The private key to import (32 or 64 bytes). Can be a base58 encoded string or raw bytes.
148
+ * @param {string} [options.name] - The name of the account.
149
+ * @param {string} [options.encryptionPublicKey] - The RSA public key for encrypting the private key.
150
+ * @param {string} [options.idempotencyKey] - An idempotency key.
151
+ *
152
+ * @returns A promise that resolves to the imported account.
153
+ *
154
+ * @example **Import with private key only**
155
+ * ```ts
156
+ * const account = await cdp.solana.importAccount({
157
+ * privateKey: "3Kzjw8qSxx8bQkV7EHrVFWYiPyNLbBVxtVe1Q5h2zKZY8DdcuT2dKxyz9kU5vQrP",
158
+ * });
159
+ * ```
160
+ *
161
+ * @example **Import with name**
162
+ * ```ts
163
+ * const account = await cdp.solana.importAccount({
164
+ * privateKey: "3Kzjw8qSxx8bQkV7EHrVFWYiPyNLbBVxtVe1Q5h2zKZY8DdcuT2dKxyz9kU5vQrP",
165
+ * name: "ImportedAccount",
166
+ * });
167
+ * ```
168
+ *
169
+ * @example **Import with idempotency key**
170
+ * ```ts
171
+ * const idempotencyKey = uuidv4();
172
+ *
173
+ * const account = await cdp.solana.importAccount({
174
+ * privateKey: "3Kzjw8qSxx8bQkV7EHrVFWYiPyNLbBVxtVe1Q5h2zKZY8DdcuT2dKxyz9kU5vQrP",
175
+ * name: "ImportedAccount",
176
+ * idempotencyKey,
177
+ * });
178
+ * ```
179
+ */
180
+ async importAccount(options: ImportAccountOptions): Promise<SolanaAccount> {
181
+ let privateKeyBytes: Uint8Array = new Uint8Array();
182
+
183
+ if (typeof options.privateKey === "string") {
184
+ privateKeyBytes = bs58.decode(options.privateKey);
185
+ } else {
186
+ privateKeyBytes = options.privateKey;
187
+ }
188
+
189
+ if (privateKeyBytes.length !== 32 && privateKeyBytes.length !== 64) {
190
+ throw new Error("Invalid private key length");
191
+ }
192
+
193
+ if (privateKeyBytes.length === 64) {
194
+ privateKeyBytes = privateKeyBytes.subarray(0, 32);
195
+ }
196
+
197
+ const encryptionPublicKey = options.encryptionPublicKey || ImportAccountPublicRSAKey;
198
+
199
+ const encryptedPrivateKey = publicEncrypt(
200
+ {
201
+ key: encryptionPublicKey,
202
+ padding: constants.RSA_PKCS1_OAEP_PADDING,
203
+ oaepHash: "sha256",
204
+ },
205
+ privateKeyBytes,
206
+ );
207
+
208
+ const openApiAccount = await CdpOpenApiClient.importSolanaAccount(
209
+ {
210
+ encryptedPrivateKey: encryptedPrivateKey.toString("base64"),
211
+ name: options.name,
212
+ },
213
+ options.idempotencyKey,
214
+ );
215
+
216
+ const account = toSolanaAccount(CdpOpenApiClient, {
217
+ account: openApiAccount,
218
+ });
219
+
220
+ Analytics.wrapObjectMethodsWithErrorTracking(account);
221
+
222
+ return account;
223
+ }
224
+
136
225
  /**
137
226
  * Gets a Solana account by its address.
138
227
  *