@coinbase/cdp-sdk 1.20.0 → 1.22.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 (144) hide show
  1. package/CHANGELOG.md +32 -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 +86 -32
  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/transferWithViem.js +2 -1
  22. package/_cjs/actions/evm/transfer/transferWithViem.js.map +1 -1
  23. package/_cjs/auth/utils/hash.js +17 -0
  24. package/_cjs/auth/utils/hash.js.map +1 -0
  25. package/_cjs/auth/utils/jwt.js +20 -55
  26. package/_cjs/auth/utils/jwt.js.map +1 -1
  27. package/_cjs/client/cdp.js +6 -0
  28. package/_cjs/client/cdp.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/solana-accounts/solana-accounts.js +10 -1
  36. package/_cjs/openapi-client/generated/solana-accounts/solana-accounts.js.map +1 -1
  37. package/_cjs/version.js +1 -1
  38. package/_esm/accounts/evm/chainToNetworkMapper.js +30 -0
  39. package/_esm/accounts/evm/chainToNetworkMapper.js.map +1 -0
  40. package/_esm/accounts/evm/getBaseNodeRpcUrl.js +35 -0
  41. package/_esm/accounts/evm/getBaseNodeRpcUrl.js.map +1 -0
  42. package/_esm/accounts/evm/networkCapabilities.js +86 -0
  43. package/_esm/accounts/evm/networkCapabilities.js.map +1 -0
  44. package/_esm/accounts/evm/resolveViemClients.js +1 -34
  45. package/_esm/accounts/evm/resolveViemClients.js.map +1 -1
  46. package/_esm/accounts/evm/toEvmServerAccount.js +1 -1
  47. package/_esm/accounts/evm/toEvmServerAccount.js.map +1 -1
  48. package/_esm/accounts/evm/toEvmSmartAccount.js +2 -2
  49. package/_esm/accounts/evm/toEvmSmartAccount.js.map +1 -1
  50. package/_esm/accounts/evm/toNetworkScopedEvmServerAccount.js +87 -33
  51. package/_esm/accounts/evm/toNetworkScopedEvmServerAccount.js.map +1 -1
  52. package/_esm/accounts/evm/toNetworkScopedEvmSmartAccount.js +126 -2
  53. package/_esm/accounts/evm/toNetworkScopedEvmSmartAccount.js.map +1 -1
  54. package/_esm/actions/evm/sendUserOperation.js +8 -1
  55. package/_esm/actions/evm/sendUserOperation.js.map +1 -1
  56. package/_esm/actions/evm/transfer/transferWithViem.js +2 -1
  57. package/_esm/actions/evm/transfer/transferWithViem.js.map +1 -1
  58. package/_esm/auth/utils/hash.js +13 -0
  59. package/_esm/auth/utils/hash.js.map +1 -0
  60. package/_esm/auth/utils/jwt.js +20 -22
  61. package/_esm/auth/utils/jwt.js.map +1 -1
  62. package/_esm/client/cdp.js +6 -0
  63. package/_esm/client/cdp.js.map +1 -1
  64. package/_esm/client/evm/evm.js +2 -2
  65. package/_esm/client/evm/evm.js.map +1 -1
  66. package/_esm/client/solana/solana.js +71 -0
  67. package/_esm/client/solana/solana.js.map +1 -1
  68. package/_esm/constants.js +17 -0
  69. package/_esm/constants.js.map +1 -1
  70. package/_esm/openapi-client/generated/solana-accounts/solana-accounts.js +8 -0
  71. package/_esm/openapi-client/generated/solana-accounts/solana-accounts.js.map +1 -1
  72. package/_esm/version.js +1 -1
  73. package/_types/accounts/evm/chainToNetworkMapper.d.ts +11 -0
  74. package/_types/accounts/evm/chainToNetworkMapper.d.ts.map +1 -0
  75. package/_types/accounts/evm/getBaseNodeRpcUrl.d.ts +8 -0
  76. package/_types/accounts/evm/getBaseNodeRpcUrl.d.ts.map +1 -0
  77. package/_types/accounts/evm/networkCapabilities.d.ts +103 -0
  78. package/_types/accounts/evm/networkCapabilities.d.ts.map +1 -0
  79. package/_types/accounts/evm/resolveViemClients.d.ts.map +1 -1
  80. package/_types/accounts/evm/toEvmServerAccount.d.ts.map +1 -1
  81. package/_types/accounts/evm/toEvmSmartAccount.d.ts.map +1 -1
  82. package/_types/accounts/evm/toNetworkScopedEvmServerAccount.d.ts +3 -3
  83. package/_types/accounts/evm/toNetworkScopedEvmServerAccount.d.ts.map +1 -1
  84. package/_types/accounts/evm/toNetworkScopedEvmSmartAccount.d.ts +9 -6
  85. package/_types/accounts/evm/toNetworkScopedEvmSmartAccount.d.ts.map +1 -1
  86. package/_types/accounts/evm/types.d.ts +109 -14
  87. package/_types/accounts/evm/types.d.ts.map +1 -1
  88. package/_types/actions/evm/fund/fund.d.ts +1 -1
  89. package/_types/actions/evm/fund/fund.d.ts.map +1 -1
  90. package/_types/actions/evm/fund/quoteFund.d.ts +1 -1
  91. package/_types/actions/evm/fund/quoteFund.d.ts.map +1 -1
  92. package/_types/actions/evm/sendUserOperation.d.ts.map +1 -1
  93. package/_types/actions/evm/transfer/transferWithViem.d.ts +1 -1
  94. package/_types/actions/evm/transfer/transferWithViem.d.ts.map +1 -1
  95. package/_types/auth/utils/hash.d.ts +9 -0
  96. package/_types/auth/utils/hash.d.ts.map +1 -0
  97. package/_types/auth/utils/jwt.d.ts.map +1 -1
  98. package/_types/client/cdp.d.ts.map +1 -1
  99. package/_types/client/evm/evm.d.ts.map +1 -1
  100. package/_types/client/evm/evm.types.d.ts +1 -1
  101. package/_types/client/evm/evm.types.d.ts.map +1 -1
  102. package/_types/client/solana/solana.d.ts +40 -1
  103. package/_types/client/solana/solana.d.ts.map +1 -1
  104. package/_types/client/solana/solana.types.d.ts +15 -1
  105. package/_types/client/solana/solana.types.d.ts.map +1 -1
  106. package/_types/constants.d.ts +4 -0
  107. package/_types/constants.d.ts.map +1 -1
  108. package/_types/openapi-client/generated/solana-accounts/solana-accounts.d.ts +5 -0
  109. package/_types/openapi-client/generated/solana-accounts/solana-accounts.d.ts.map +1 -1
  110. package/_types/openapi-client/index.d.ts +10 -0
  111. package/_types/openapi-client/index.d.ts.map +1 -1
  112. package/_types/policies/schema.d.ts +24 -24
  113. package/_types/version.d.ts +1 -1
  114. package/accounts/evm/chainToNetworkMapper.ts +37 -0
  115. package/accounts/evm/getBaseNodeRpcUrl.ts +40 -0
  116. package/accounts/evm/networkCapabilities.ts +117 -0
  117. package/accounts/evm/resolveViemClients.ts +1 -38
  118. package/accounts/evm/toEvmServerAccount.ts +3 -3
  119. package/accounts/evm/toEvmSmartAccount.ts +3 -3
  120. package/accounts/evm/toNetworkScopedEvmServerAccount.ts +116 -44
  121. package/accounts/evm/toNetworkScopedEvmSmartAccount.ts +178 -11
  122. package/accounts/evm/types.ts +253 -25
  123. package/actions/evm/fund/fund.ts +1 -1
  124. package/actions/evm/fund/quoteFund.ts +1 -1
  125. package/actions/evm/sendUserOperation.ts +9 -1
  126. package/actions/evm/transfer/transferWithViem.ts +4 -3
  127. package/auth/utils/hash.ts +13 -0
  128. package/auth/utils/jwt.ts +21 -24
  129. package/client/cdp.ts +9 -0
  130. package/client/evm/evm.ts +2 -2
  131. package/client/evm/evm.types.ts +1 -1
  132. package/client/solana/solana.ts +89 -0
  133. package/client/solana/solana.types.ts +16 -0
  134. package/constants.ts +18 -0
  135. package/openapi-client/generated/solana-accounts/solana-accounts.ts +20 -0
  136. package/package.json +2 -1
  137. package/version.ts +1 -1
  138. package/_cjs/client/evm/constants.js +0 -21
  139. package/_cjs/client/evm/constants.js.map +0 -1
  140. package/_esm/client/evm/constants.js +0 -18
  141. package/_esm/client/evm/constants.js.map +0 -1
  142. package/_types/client/evm/constants.d.ts +0 -5
  143. package/_types/client/evm/constants.d.ts.map +0 -1
  144. package/client/evm/constants.ts +0 -17
@@ -1,7 +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";
3
- import { TransferOptions } from "../../actions/evm/transfer/types.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";
4
43
 
44
+ import type {
45
+ SmartAccountTransferOptions,
46
+ TransferOptions,
47
+ } from "../../actions/evm/transfer/types.js";
5
48
  import type { AccountActions, SmartAccountActions } from "../../actions/evm/types.js";
6
49
  import type { Address, Hash, Hex } from "../../types/misc.js";
7
50
  import type { Prettify } from "../../types/utils.js";
@@ -38,6 +81,27 @@ export type EvmAccount = {
38
81
  policies?: string[];
39
82
  };
40
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
+
41
105
  /**
42
106
  * Server-managed ethereum account
43
107
  */
@@ -48,8 +112,23 @@ export type EvmServerAccount = Prettify<
48
112
  name?: string;
49
113
  /** Indicates this is a server-managed account. */
50
114
  type: "evm-server";
51
- /** A function that returns a network-scoped server-managed account. */
52
- 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>>;
53
132
  }
54
133
  >;
55
134
 
@@ -62,8 +141,23 @@ type EvmSmartAccountProperties = {
62
141
  owners: EvmAccount[];
63
142
  /** Identifier for the smart account type. */
64
143
  type: "evm-smart";
65
- /** Subject to breaking changes. A function that returns a network-scoped smart account. */
66
- __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>>;
67
161
  };
68
162
 
69
163
  /**
@@ -71,33 +165,167 @@ type EvmSmartAccountProperties = {
71
165
  */
72
166
  export type EvmSmartAccount = Prettify<EvmSmartAccountProperties & SmartAccountActions>;
73
167
 
74
- export type NetworkScopedEvmSmartAccount = Prettify<
75
- Omit<EvmSmartAccountProperties, "__experimental_useNetwork"> & {
76
- /** The network to scope the smart account object to. */
77
- network: string;
78
- }
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
+ }
79
251
  >;
80
252
 
81
- type NetworkScopedAccountActions = Prettify<{
82
- requestFaucet: (
83
- options: Omit<RequestFaucetOptions, "address" | "network">,
84
- ) => Promise<RequestFaucetResult>;
85
- sendTransaction: (
86
- options: Omit<SendTransactionOptions, "address" | "network">,
87
- ) => Promise<TransactionResult>;
88
- waitForTransactionReceipt: (
89
- options: WaitForTransactionReceiptParameters | TransactionResult,
90
- ) => Promise<TransactionReceipt>;
91
- transfer: (options: Omit<TransferOptions, "address" | "network">) => Promise<TransactionResult>;
92
- }>;
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
+ >;
93
321
 
94
322
  /**
95
323
  * A network-scoped server-managed ethereum account
96
324
  */
97
- export type NetworkScopedEvmServerAccount = Prettify<
325
+ export type NetworkScopedEvmServerAccount<Network extends string = string> = Prettify<
98
326
  Omit<EvmServerAccount, keyof AccountActions | "useNetwork"> &
99
- NetworkScopedAccountActions & {
327
+ NetworkSpecificAccountActions<Network> & {
100
328
  /** The network this account is scoped to */
101
- network: string;
329
+ network: Network;
102
330
  }
103
331
  >;
@@ -14,7 +14,7 @@ export interface FundOptions {
14
14
  /** The address of the account. */
15
15
  address: string;
16
16
  /** The network to request funds from. */
17
- network: "base";
17
+ network: "base" | "ethereum";
18
18
  /** The amount to fund the account with, in atomic units (wei) of the token. */
19
19
  amount: bigint;
20
20
  /** The token to request funds for. */
@@ -14,7 +14,7 @@ export interface QuoteFundOptions {
14
14
  /** The address of the account. */
15
15
  address: string;
16
16
  /** The network to request funds from. */
17
- network: "base";
17
+ network: "base" | "ethereum";
18
18
  /** The amount to fund the account with, in atomic units (wei) of the token. */
19
19
  amount: bigint;
20
20
  /** The token to request funds for. */
@@ -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");
@@ -1,6 +1,7 @@
1
1
  import { encodeFunctionData, erc20Abi } from "viem";
2
2
 
3
3
  import { getErc20Address } from "./utils.js";
4
+ import { mapChainToNetwork } from "../../../accounts/evm/chainToNetworkMapper.js";
4
5
 
5
6
  import type { Network, TransferOptions } from "./types.js";
6
7
  import type { EvmAccount } from "../../../accounts/evm/types.js";
@@ -21,12 +22,11 @@ import type { Account, Chain, Transport, WalletClient } from "viem";
21
22
  export async function transferWithViem<T extends EvmAccount>(
22
23
  walletClient: WalletClient<Transport, Chain, Account>,
23
24
  from: T,
24
- transferArgs: TransferOptions,
25
+ transferArgs: Omit<TransferOptions, "address" | "network">,
25
26
  ): Promise<TransactionResult> {
26
27
  const token = transferArgs.token;
27
28
  const to = typeof transferArgs.to === "string" ? transferArgs.to : transferArgs.to.address;
28
29
  const value = transferArgs.amount;
29
- const network = transferArgs.network;
30
30
 
31
31
  if (token === "eth") {
32
32
  const hash = await walletClient.sendTransaction({
@@ -37,7 +37,8 @@ export async function transferWithViem<T extends EvmAccount>(
37
37
  return { transactionHash: hash as Hex };
38
38
  }
39
39
 
40
- const erc20Address = getErc20Address(token, network as Network);
40
+ const network = mapChainToNetwork(walletClient.chain) as Network;
41
+ const erc20Address = getErc20Address(token, network);
41
42
 
42
43
  // First approve the transfer
43
44
  await walletClient.sendTransaction({
@@ -0,0 +1,13 @@
1
+ import { subtle } from "uncrypto";
2
+
3
+ /**
4
+ * Auth-specific hash function using uncrypto for Edge runtime compatibility.
5
+ * Computes SHA-256 hash of the given data.
6
+ *
7
+ * @param data - The data to hash
8
+ * @returns Promise that resolves to the hex-encoded hash
9
+ */
10
+ export const authHash = async (data: Buffer): Promise<string> => {
11
+ const hashBuffer = await subtle.digest("SHA-256", data);
12
+ return Buffer.from(hashBuffer).toString("hex");
13
+ };
package/auth/utils/jwt.ts CHANGED
@@ -1,9 +1,7 @@
1
- import * as crypto from "crypto";
2
- import { createPrivateKey } from "crypto";
3
-
4
1
  import { SignJWT, importPKCS8, importJWK, JWTPayload } from "jose";
2
+ import { getRandomValues } from "uncrypto";
5
3
 
6
- import { hash } from "../../utils/hash.js";
4
+ import { authHash } from "./hash.js";
7
5
  import { sortKeys } from "../../utils/sortKeys.js";
8
6
  import { InvalidWalletSecretFormatError, UndefinedWalletSecretError } from "../errors.js";
9
7
 
@@ -147,7 +145,7 @@ export async function generateJwt(options: JwtOptions): Promise<string> {
147
145
  const randomNonce = nonce();
148
146
 
149
147
  // Determine if we're using EC or Edwards key based on the key format
150
- if (isValidECKey(options.apiKeySecret)) {
148
+ if (await isValidECKey(options.apiKeySecret)) {
151
149
  return await buildECJWT(
152
150
  options.apiKeySecret,
153
151
  options.apiKeyId,
@@ -193,16 +191,18 @@ export async function generateWalletJwt(options: WalletJwtOptions): Promise<stri
193
191
 
194
192
  if (Object.keys(options.requestData).length > 0) {
195
193
  const sortedData = sortKeys(options.requestData);
196
- claims.reqHash = hash(Buffer.from(JSON.stringify(sortedData)));
194
+ claims.reqHash = await authHash(Buffer.from(JSON.stringify(sortedData)));
197
195
  }
198
196
 
199
197
  try {
200
- const ecKey = createPrivateKey({
201
- key: options.walletSecret,
202
- format: "der",
203
- type: "pkcs8",
204
- encoding: "base64",
205
- });
198
+ // Convert base64 DER to PEM format for jose
199
+ const derBuffer = Buffer.from(options.walletSecret, "base64");
200
+ const pemKey = `-----BEGIN PRIVATE KEY-----\n${derBuffer
201
+ .toString("base64")
202
+ .match(/.{1,64}/g)
203
+ ?.join("\n")}\n-----END PRIVATE KEY-----`;
204
+
205
+ const ecKey = await importPKCS8(pemKey, "ES256");
206
206
 
207
207
  return await new SignJWT(claims)
208
208
  .setProtectedHeader({ alg: "ES256", typ: "JWT" })
@@ -236,12 +236,11 @@ function isValidEd25519Key(str: string): boolean {
236
236
  * @param str - The string to test
237
237
  * @returns True if the string is a valid EC private key in PEM format
238
238
  */
239
- function isValidECKey(str: string): boolean {
239
+ async function isValidECKey(str: string): Promise<boolean> {
240
240
  try {
241
- // Attempt to create a private key object - will throw if invalid
242
- const key = createPrivateKey(str);
243
- // Check if it's an EC key by examining its asymmetric key type
244
- return key.asymmetricKeyType === "ec";
241
+ // Try to import the key with jose - if it works, it's a valid EC key
242
+ await importPKCS8(str, "ES256");
243
+ return true;
245
244
  } catch {
246
245
  return false;
247
246
  }
@@ -268,12 +267,8 @@ async function buildECJWT(
268
267
  nonce: string,
269
268
  ): Promise<string> {
270
269
  try {
271
- // Convert to PKCS8 format
272
- const keyObj = createPrivateKey(privateKey);
273
- const pkcs8Key = keyObj.export({ type: "pkcs8", format: "pem" }).toString();
274
-
275
- // Import the key for signing
276
- const ecKey = await importPKCS8(pkcs8Key, "ES256");
270
+ // Import the key directly with jose
271
+ const ecKey = await importPKCS8(privateKey, "ES256");
277
272
 
278
273
  // Sign and return the JWT
279
274
  return await new SignJWT(claims)
@@ -346,5 +341,7 @@ async function buildEdwardsJWT(
346
341
  * @returns {string} The generated nonce.
347
342
  */
348
343
  function nonce(): string {
349
- return crypto.randomBytes(16).toString("hex");
344
+ const bytes = new Uint8Array(16);
345
+ getRandomValues(bytes);
346
+ return Buffer.from(bytes).toString("hex");
350
347
  }
package/client/cdp.ts CHANGED
@@ -67,6 +67,15 @@ export class CdpClient {
67
67
  * @param {CdpClientOptions} [options] - Configuration options for the CdpClient.
68
68
  */
69
69
  constructor(options: CdpClientOptions = {}) {
70
+ if (Number(process.versions.node.split(".")[0]) < 19) {
71
+ throw new Error(
72
+ `
73
+ Node.js version ${process.versions.node} is not supported. CDP SDK requires Node.js version 19 or higher. Please upgrade your Node.js version to use the CDP SDK.
74
+ We recommend using https://github.com/Schniz/fnm for managing your Node.js version.
75
+ `,
76
+ );
77
+ }
78
+
70
79
  const apiKeyId = options.apiKeyId ?? process.env.CDP_API_KEY_ID ?? process.env.CDP_API_KEY_NAME;
71
80
  const apiKeySecret = options.apiKeySecret ?? process.env.CDP_API_KEY_SECRET;
72
81
  const walletSecret = options.walletSecret ?? process.env.CDP_WALLET_SECRET;
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
  *