@coinbase/cdp-sdk 1.18.0 → 1.20.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 (111) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/_cjs/accounts/evm/resolveViemClients.js +39 -2
  3. package/_cjs/accounts/evm/resolveViemClients.js.map +1 -1
  4. package/_cjs/accounts/evm/toNetworkScopedEvmServerAccount.js +20 -0
  5. package/_cjs/accounts/evm/toNetworkScopedEvmServerAccount.js.map +1 -1
  6. package/_cjs/actions/evm/transfer/smartAccountTransferStrategy.js +3 -2
  7. package/_cjs/actions/evm/transfer/smartAccountTransferStrategy.js.map +1 -1
  8. package/_cjs/actions/evm/transfer/transfer.js +4 -0
  9. package/_cjs/actions/evm/transfer/transfer.js.map +1 -1
  10. package/_cjs/actions/evm/transfer/transferWithViem.js +52 -0
  11. package/_cjs/actions/evm/transfer/transferWithViem.js.map +1 -0
  12. package/_cjs/actions/evm/transfer/types.js +25 -0
  13. package/_cjs/actions/evm/transfer/types.js.map +1 -1
  14. package/_cjs/auth/hooks/axios/withAuth.js +5 -0
  15. package/_cjs/auth/hooks/axios/withAuth.js.map +1 -1
  16. package/_cjs/auth/utils/jwt.js +4 -1
  17. package/_cjs/auth/utils/jwt.js.map +1 -1
  18. package/_cjs/index.js +3 -1
  19. package/_cjs/index.js.map +1 -1
  20. package/_cjs/openapi-client/cdpApiClient.js +8 -2
  21. package/_cjs/openapi-client/cdpApiClient.js.map +1 -1
  22. package/_cjs/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js +4 -0
  23. package/_cjs/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js.map +1 -1
  24. package/_cjs/openapi-client/generated/index.msw.js +4 -4
  25. package/_cjs/openapi-client/generated/index.msw.js.map +1 -1
  26. package/_cjs/utils/bigint.js +24 -0
  27. package/_cjs/utils/bigint.js.map +1 -0
  28. package/_cjs/utils/hash.js +7 -0
  29. package/_cjs/utils/hash.js.map +1 -0
  30. package/_cjs/utils/sortKeys.js +26 -0
  31. package/_cjs/utils/sortKeys.js.map +1 -0
  32. package/_cjs/version.js +1 -1
  33. package/_esm/accounts/evm/resolveViemClients.js +39 -2
  34. package/_esm/accounts/evm/resolveViemClients.js.map +1 -1
  35. package/_esm/accounts/evm/toNetworkScopedEvmServerAccount.js +20 -0
  36. package/_esm/accounts/evm/toNetworkScopedEvmServerAccount.js.map +1 -1
  37. package/_esm/actions/evm/transfer/smartAccountTransferStrategy.js +3 -2
  38. package/_esm/actions/evm/transfer/smartAccountTransferStrategy.js.map +1 -1
  39. package/_esm/actions/evm/transfer/transfer.js +4 -0
  40. package/_esm/actions/evm/transfer/transfer.js.map +1 -1
  41. package/_esm/actions/evm/transfer/transferWithViem.js +49 -0
  42. package/_esm/actions/evm/transfer/transferWithViem.js.map +1 -0
  43. package/_esm/actions/evm/transfer/types.js +23 -1
  44. package/_esm/actions/evm/transfer/types.js.map +1 -1
  45. package/_esm/auth/hooks/axios/withAuth.js +5 -0
  46. package/_esm/auth/hooks/axios/withAuth.js.map +1 -1
  47. package/_esm/auth/utils/jwt.js +4 -1
  48. package/_esm/auth/utils/jwt.js.map +1 -1
  49. package/_esm/index.js +1 -0
  50. package/_esm/index.js.map +1 -1
  51. package/_esm/openapi-client/cdpApiClient.js +7 -1
  52. package/_esm/openapi-client/cdpApiClient.js.map +1 -1
  53. package/_esm/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js +4 -0
  54. package/_esm/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js.map +1 -1
  55. package/_esm/openapi-client/generated/index.msw.js +4 -4
  56. package/_esm/openapi-client/generated/index.msw.js.map +1 -1
  57. package/_esm/utils/bigint.js +20 -0
  58. package/_esm/utils/bigint.js.map +1 -0
  59. package/_esm/utils/hash.js +3 -0
  60. package/_esm/utils/hash.js.map +1 -0
  61. package/_esm/utils/sortKeys.js +22 -0
  62. package/_esm/utils/sortKeys.js.map +1 -0
  63. package/_esm/version.js +1 -1
  64. package/_types/accounts/evm/resolveViemClients.d.ts.map +1 -1
  65. package/_types/accounts/evm/toNetworkScopedEvmServerAccount.d.ts.map +1 -1
  66. package/_types/accounts/evm/types.d.ts +3 -1
  67. package/_types/accounts/evm/types.d.ts.map +1 -1
  68. package/_types/actions/evm/swap/types.d.ts +9 -4
  69. package/_types/actions/evm/swap/types.d.ts.map +1 -1
  70. package/_types/actions/evm/transfer/smartAccountTransferStrategy.d.ts.map +1 -1
  71. package/_types/actions/evm/transfer/transfer.d.ts.map +1 -1
  72. package/_types/actions/evm/transfer/transferWithViem.d.ts +16 -0
  73. package/_types/actions/evm/transfer/transferWithViem.d.ts.map +1 -0
  74. package/_types/actions/evm/transfer/types.d.ts +17 -1
  75. package/_types/actions/evm/transfer/types.d.ts.map +1 -1
  76. package/_types/auth/hooks/axios/withAuth.d.ts.map +1 -1
  77. package/_types/auth/utils/jwt.d.ts.map +1 -1
  78. package/_types/index.d.ts +1 -0
  79. package/_types/index.d.ts.map +1 -1
  80. package/_types/openapi-client/cdpApiClient.d.ts +4 -0
  81. package/_types/openapi-client/cdpApiClient.d.ts.map +1 -1
  82. package/_types/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.d.ts +4 -0
  83. package/_types/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.d.ts.map +1 -1
  84. package/_types/openapi-client/generated/index.msw.d.ts +4 -4
  85. package/_types/openapi-client/generated/index.msw.d.ts.map +1 -1
  86. package/_types/utils/bigint.d.ts +8 -0
  87. package/_types/utils/bigint.d.ts.map +1 -0
  88. package/_types/utils/hash.d.ts +2 -0
  89. package/_types/utils/hash.d.ts.map +1 -0
  90. package/_types/utils/sortKeys.d.ts +8 -0
  91. package/_types/utils/sortKeys.d.ts.map +1 -0
  92. package/_types/version.d.ts +1 -1
  93. package/accounts/evm/resolveViemClients.ts +46 -2
  94. package/accounts/evm/toNetworkScopedEvmServerAccount.ts +24 -1
  95. package/accounts/evm/types.ts +3 -1
  96. package/actions/evm/swap/types.ts +11 -3
  97. package/actions/evm/transfer/smartAccountTransferStrategy.ts +5 -2
  98. package/actions/evm/transfer/transfer.ts +8 -0
  99. package/actions/evm/transfer/transferWithViem.ts +65 -0
  100. package/actions/evm/transfer/types.ts +31 -1
  101. package/auth/hooks/axios/withAuth.ts +6 -0
  102. package/auth/utils/jwt.ts +4 -1
  103. package/index.ts +2 -0
  104. package/openapi-client/cdpApiClient.ts +13 -1
  105. package/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.ts +4 -0
  106. package/openapi-client/generated/index.msw.ts +4 -4
  107. package/package.json +1 -1
  108. package/utils/bigint.ts +19 -0
  109. package/utils/hash.ts +3 -0
  110. package/utils/sortKeys.ts +26 -0
  111. package/version.ts +1 -1
@@ -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,65 @@
1
+ import { encodeFunctionData, erc20Abi } from "viem";
2
+
3
+ import { getErc20Address } from "./utils.js";
4
+
5
+ import type { Network, TransferOptions } from "./types.js";
6
+ import type { EvmAccount } from "../../../accounts/evm/types.js";
7
+ import type { Hex } from "../../../types/misc.js";
8
+ import type { TransactionResult } from "../sendTransaction.js";
9
+ import type { Account, Chain, Transport, WalletClient } from "viem";
10
+
11
+ /**
12
+ * Transfer an amount of a token from a network-scoped account to another account.
13
+ * This function is used for accounts that are scoped to a specific network and use
14
+ * a wallet client for transaction execution instead of the API client.
15
+ *
16
+ * @param walletClient - The wallet client to use for transaction execution.
17
+ * @param from - The account to send the transaction from.
18
+ * @param transferArgs - The transfer options.
19
+ * @returns The result of the transfer.
20
+ */
21
+ export async function transferWithViem<T extends EvmAccount>(
22
+ walletClient: WalletClient<Transport, Chain, Account>,
23
+ from: T,
24
+ transferArgs: TransferOptions,
25
+ ): Promise<TransactionResult> {
26
+ const token = transferArgs.token;
27
+ const to = typeof transferArgs.to === "string" ? transferArgs.to : transferArgs.to.address;
28
+ const value = transferArgs.amount;
29
+ const network = transferArgs.network;
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 erc20Address = getErc20Address(token, network as Network);
41
+
42
+ // First approve the transfer
43
+ await walletClient.sendTransaction({
44
+ account: from.address,
45
+ to: erc20Address,
46
+ data: encodeFunctionData({
47
+ abi: erc20Abi,
48
+ functionName: "approve",
49
+ args: [to, value],
50
+ }),
51
+ });
52
+
53
+ // Then execute the transfer
54
+ const hash = await walletClient.sendTransaction({
55
+ account: from.address,
56
+ to: erc20Address,
57
+ data: encodeFunctionData({
58
+ abi: erc20Abi,
59
+ functionName: "transfer",
60
+ args: [to, value],
61
+ }),
62
+ });
63
+
64
+ return { transactionHash: hash as Hex };
65
+ }
@@ -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
+ }
@@ -1,5 +1,6 @@
1
1
  import { AxiosInstance, AxiosHeaders } from "axios";
2
2
 
3
+ import { convertBigIntsToStrings } from "../../../utils/bigint.js";
3
4
  import { getAuthHeaders } from "../../utils/http.js";
4
5
 
5
6
  export interface AuthInterceptorOptions {
@@ -57,6 +58,11 @@ export function withAuth(axiosClient: AxiosInstance, options: AuthInterceptorOpt
57
58
  // Parse URL to get host and path
58
59
  const url = new URL(fullyQualifiedURL);
59
60
 
61
+ // Convert bigints in request body to strings for safe serialization
62
+ if (axiosConfig.data) {
63
+ axiosConfig.data = convertBigIntsToStrings(axiosConfig.data);
64
+ }
65
+
60
66
  // Get authentication headers
61
67
  const headers = await getAuthHeaders({
62
68
  apiKeyId: options.apiKeyId,
package/auth/utils/jwt.ts CHANGED
@@ -3,6 +3,8 @@ import { createPrivateKey } from "crypto";
3
3
 
4
4
  import { SignJWT, importPKCS8, importJWK, JWTPayload } from "jose";
5
5
 
6
+ import { hash } from "../../utils/hash.js";
7
+ import { sortKeys } from "../../utils/sortKeys.js";
6
8
  import { InvalidWalletSecretFormatError, UndefinedWalletSecretError } from "../errors.js";
7
9
 
8
10
  /**
@@ -190,7 +192,8 @@ export async function generateWalletJwt(options: WalletJwtOptions): Promise<stri
190
192
  };
191
193
 
192
194
  if (Object.keys(options.requestData).length > 0) {
193
- claims.req = options.requestData;
195
+ const sortedData = sortKeys(options.requestData);
196
+ claims.reqHash = hash(Buffer.from(JSON.stringify(sortedData)));
194
197
  }
195
198
 
196
199
  try {
package/index.ts CHANGED
@@ -7,3 +7,5 @@ export {
7
7
  type CreatePolicyBody,
8
8
  type UpdatePolicyBody,
9
9
  } from "./policies/schema.js";
10
+
11
+ export { parseEther } from "viem";
@@ -11,6 +11,8 @@ import {
11
11
  UnknownError,
12
12
  } from "./errors.js";
13
13
 
14
+ import type { Prettify } from "../types/utils.js";
15
+
14
16
  /**
15
17
  * The options for the CDP API.
16
18
  */
@@ -54,14 +56,24 @@ export type CdpOptions = {
54
56
 
55
57
  let axiosInstance: AxiosInstance;
56
58
 
59
+ export let config: Prettify<Omit<CdpOptions, "basePath"> & { basePath: string }> | undefined =
60
+ undefined;
61
+
57
62
  /**
58
63
  * Configures the CDP client with the given options.
59
64
  *
60
65
  * @param {CdpOptions} options - The CDP options.
61
66
  */
62
67
  export const configure = (options: CdpOptions) => {
68
+ const baseURL = options.basePath || "https://api.cdp.coinbase.com/platform";
69
+
70
+ config = {
71
+ ...options,
72
+ basePath: baseURL,
73
+ };
74
+
63
75
  axiosInstance = Axios.create({
64
- baseURL: options.basePath || "https://api.cdp.coinbase.com/platform",
76
+ baseURL,
65
77
  });
66
78
 
67
79
  axiosInstance = withAuth(axiosInstance, {
@@ -56,6 +56,7 @@ export const ErrorType = {
56
56
  unauthorized: "unauthorized",
57
57
  policy_violation: "policy_violation",
58
58
  policy_in_use: "policy_in_use",
59
+ account_limit_exceeded: "account_limit_exceeded",
59
60
  } as const;
60
61
 
61
62
  /**
@@ -487,6 +488,7 @@ export type ListEvmTokenBalancesNetwork =
487
488
  export const ListEvmTokenBalancesNetwork = {
488
489
  base: "base",
489
490
  "base-sepolia": "base-sepolia",
491
+ ethereum: "ethereum",
490
492
  } as const;
491
493
 
492
494
  /**
@@ -1488,6 +1490,8 @@ export type SendEvmTransactionBodyNetwork =
1488
1490
  export const SendEvmTransactionBodyNetwork = {
1489
1491
  base: "base",
1490
1492
  "base-sepolia": "base-sepolia",
1493
+ ethereum: "ethereum",
1494
+ "ethereum-sepolia": "ethereum-sepolia",
1491
1495
  } as const;
1492
1496
 
1493
1497
  export type SendEvmTransactionBody = {
@@ -1,8 +1,8 @@
1
1
  export * from "./evm-token-balances/evm-token-balances.msw.js";
2
- export * from "./evm-accounts/evm-accounts.msw.js";
3
- export * from "./evm-smart-accounts/evm-smart-accounts.msw.js";
4
2
  export * from "./faucets/faucets.msw.js";
3
+ export * from "./evm-accounts/evm-accounts.msw.js";
5
4
  export * from "./evm-swaps/evm-swaps.msw.js";
6
- export * from "./payments-alpha/payments-alpha.msw.js";
7
- export * from "./policy-engine/policy-engine.msw.js";
8
5
  export * from "./solana-accounts/solana-accounts.msw.js";
6
+ export * from "./policy-engine/policy-engine.msw.js";
7
+ export * from "./payments-alpha/payments-alpha.msw.js";
8
+ export * from "./evm-smart-accounts/evm-smart-accounts.msw.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinbase/cdp-sdk",
3
- "version": "1.18.0",
3
+ "version": "1.20.0",
4
4
  "description": "SDK for interacting with the Coinbase Developer Platform Wallet API",
5
5
  "main": "./_cjs/index.js",
6
6
  "module": "./_esm/index.js",
@@ -0,0 +1,19 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /**
3
+ * Converts bigint values in an object to strings for safe serialization
4
+ *
5
+ * @param obj - The object to convert
6
+ * @returns A new object with bigint values converted to strings
7
+ */
8
+ export const convertBigIntsToStrings = (obj: any): any => {
9
+ if (typeof obj === "bigint") {
10
+ return obj.toString();
11
+ }
12
+ if (Array.isArray(obj)) {
13
+ return obj.map(convertBigIntsToStrings);
14
+ }
15
+ if (obj && typeof obj === "object") {
16
+ return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, convertBigIntsToStrings(v)]));
17
+ }
18
+ return obj;
19
+ };
package/utils/hash.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { createHash } from "crypto";
2
+
3
+ export const hash = (data: Buffer) => createHash("sha256").update(data).digest("hex");
@@ -0,0 +1,26 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /**
3
+ * Recursively sorts object keys to ensure consistent JSON stringification
4
+ *
5
+ * @param obj - The object to sort
6
+ * @returns A new object with sorted keys
7
+ */
8
+ export const sortKeys = (obj: any): any => {
9
+ if (!obj || typeof obj !== "object") {
10
+ return obj;
11
+ }
12
+
13
+ if (Array.isArray(obj)) {
14
+ return obj.map(sortKeys);
15
+ }
16
+
17
+ return Object.keys(obj)
18
+ .sort()
19
+ .reduce(
20
+ (acc, key) => {
21
+ acc[key] = sortKeys(obj[key]);
22
+ return acc;
23
+ },
24
+ {} as Record<string, any>,
25
+ );
26
+ };
package/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = "1.18.0";
1
+ export const version = "1.20.0";