@coinbase/cdp-sdk 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +116 -1
  3. package/_cjs/analytics.js +25 -6
  4. package/_cjs/analytics.js.map +1 -1
  5. package/_cjs/auth/hooks/axios/withAuth.js +1 -0
  6. package/_cjs/auth/hooks/axios/withAuth.js.map +1 -1
  7. package/_cjs/client/cdp.js +2 -0
  8. package/_cjs/client/cdp.js.map +1 -1
  9. package/_cjs/client/evm/evm.js +119 -0
  10. package/_cjs/client/evm/evm.js.map +1 -1
  11. package/_cjs/openapi-client/cdpApiClient.js +16 -50
  12. package/_cjs/openapi-client/cdpApiClient.js.map +1 -1
  13. package/_cjs/openapi-client/errors.js +38 -3
  14. package/_cjs/openapi-client/errors.js.map +1 -1
  15. package/_cjs/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js +12 -1
  16. package/_cjs/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js.map +1 -1
  17. package/_cjs/openapi-client/generated/evm-accounts/evm-accounts.js +39 -4
  18. package/_cjs/openapi-client/generated/evm-accounts/evm-accounts.js.map +1 -1
  19. package/_cjs/openapi-client/generated/evm-accounts/evm-accounts.msw.js +15 -1
  20. package/_cjs/openapi-client/generated/evm-accounts/evm-accounts.msw.js.map +1 -1
  21. package/_cjs/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.js +1 -0
  22. package/_cjs/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.js.map +1 -1
  23. package/_cjs/openapi-client/generated/evm-token-balances/evm-token-balances.js +15 -0
  24. package/_cjs/openapi-client/generated/evm-token-balances/evm-token-balances.js.map +1 -0
  25. package/_cjs/openapi-client/generated/evm-token-balances/evm-token-balances.msw.js +45 -0
  26. package/_cjs/openapi-client/generated/evm-token-balances/evm-token-balances.msw.js.map +1 -0
  27. package/_cjs/openapi-client/generated/faucets/faucets.js +2 -1
  28. package/_cjs/openapi-client/generated/faucets/faucets.js.map +1 -1
  29. package/_cjs/openapi-client/generated/index.msw.js +2 -1
  30. package/_cjs/openapi-client/generated/index.msw.js.map +1 -1
  31. package/_cjs/openapi-client/index.js +4 -0
  32. package/_cjs/openapi-client/index.js.map +1 -1
  33. package/_cjs/version.js +1 -1
  34. package/_esm/analytics.js +23 -6
  35. package/_esm/analytics.js.map +1 -1
  36. package/_esm/auth/hooks/axios/withAuth.js +1 -0
  37. package/_esm/auth/hooks/axios/withAuth.js.map +1 -1
  38. package/_esm/client/cdp.js +2 -0
  39. package/_esm/client/cdp.js.map +1 -1
  40. package/_esm/client/evm/evm.js +119 -0
  41. package/_esm/client/evm/evm.js.map +1 -1
  42. package/_esm/openapi-client/cdpApiClient.js +13 -17
  43. package/_esm/openapi-client/cdpApiClient.js.map +1 -1
  44. package/_esm/openapi-client/errors.js +35 -2
  45. package/_esm/openapi-client/errors.js.map +1 -1
  46. package/_esm/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js +11 -0
  47. package/_esm/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js.map +1 -1
  48. package/_esm/openapi-client/generated/evm-accounts/evm-accounts.js +37 -3
  49. package/_esm/openapi-client/generated/evm-accounts/evm-accounts.js.map +1 -1
  50. package/_esm/openapi-client/generated/evm-accounts/evm-accounts.msw.js +12 -0
  51. package/_esm/openapi-client/generated/evm-accounts/evm-accounts.msw.js.map +1 -1
  52. package/_esm/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.js +1 -0
  53. package/_esm/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.js.map +1 -1
  54. package/_esm/openapi-client/generated/evm-token-balances/evm-token-balances.js +11 -0
  55. package/_esm/openapi-client/generated/evm-token-balances/evm-token-balances.js.map +1 -0
  56. package/_esm/openapi-client/generated/evm-token-balances/evm-token-balances.msw.js +39 -0
  57. package/_esm/openapi-client/generated/evm-token-balances/evm-token-balances.msw.js.map +1 -0
  58. package/_esm/openapi-client/generated/faucets/faucets.js +2 -1
  59. package/_esm/openapi-client/generated/faucets/faucets.js.map +1 -1
  60. package/_esm/openapi-client/generated/index.msw.js +2 -1
  61. package/_esm/openapi-client/generated/index.msw.js.map +1 -1
  62. package/_esm/openapi-client/index.js +4 -0
  63. package/_esm/openapi-client/index.js.map +1 -1
  64. package/_esm/version.js +1 -1
  65. package/_types/analytics.d.ts +15 -0
  66. package/_types/analytics.d.ts.map +1 -1
  67. package/_types/auth/hooks/axios/withAuth.d.ts.map +1 -1
  68. package/_types/client/cdp.d.ts.map +1 -1
  69. package/_types/client/evm/evm.d.ts +83 -1
  70. package/_types/client/evm/evm.d.ts.map +1 -1
  71. package/_types/client/evm/evm.types.d.ts +100 -4
  72. package/_types/client/evm/evm.types.d.ts.map +1 -1
  73. package/_types/openapi-client/cdpApiClient.d.ts.map +1 -1
  74. package/_types/openapi-client/errors.d.ts +28 -1
  75. package/_types/openapi-client/errors.d.ts.map +1 -1
  76. package/_types/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.d.ts +87 -2
  77. package/_types/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.d.ts.map +1 -1
  78. package/_types/openapi-client/generated/evm-accounts/evm-accounts.d.ts +32 -4
  79. package/_types/openapi-client/generated/evm-accounts/evm-accounts.d.ts.map +1 -1
  80. package/_types/openapi-client/generated/evm-accounts/evm-accounts.msw.d.ts +3 -1
  81. package/_types/openapi-client/generated/evm-accounts/evm-accounts.msw.d.ts.map +1 -1
  82. package/_types/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.d.ts +1 -0
  83. package/_types/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.d.ts.map +1 -1
  84. package/_types/openapi-client/generated/evm-token-balances/evm-token-balances.d.ts +20 -0
  85. package/_types/openapi-client/generated/evm-token-balances/evm-token-balances.d.ts.map +1 -0
  86. package/_types/openapi-client/generated/evm-token-balances/evm-token-balances.msw.d.ts +6 -0
  87. package/_types/openapi-client/generated/evm-token-balances/evm-token-balances.msw.d.ts.map +1 -0
  88. package/_types/openapi-client/generated/faucets/faucets.d.ts +2 -1
  89. package/_types/openapi-client/generated/faucets/faucets.d.ts.map +1 -1
  90. package/_types/openapi-client/generated/index.msw.d.ts +2 -1
  91. package/_types/openapi-client/generated/index.msw.d.ts.map +1 -1
  92. package/_types/openapi-client/index.d.ts +5 -0
  93. package/_types/openapi-client/index.d.ts.map +1 -1
  94. package/_types/types/misc.d.ts +37 -0
  95. package/_types/types/misc.d.ts.map +1 -1
  96. package/_types/version.d.ts +1 -1
  97. package/analytics.ts +26 -7
  98. package/auth/hooks/axios/withAuth.ts +1 -0
  99. package/client/cdp.ts +3 -0
  100. package/client/evm/evm.ts +134 -1
  101. package/client/evm/evm.types.ts +113 -8
  102. package/openapi-client/cdpApiClient.ts +28 -21
  103. package/openapi-client/errors.ts +37 -1
  104. package/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.ts +103 -2
  105. package/openapi-client/generated/evm-accounts/evm-accounts.msw.ts +29 -0
  106. package/openapi-client/generated/evm-accounts/evm-accounts.ts +47 -3
  107. package/openapi-client/generated/evm-smart-accounts/evm-smart-accounts.ts +1 -0
  108. package/openapi-client/generated/evm-token-balances/evm-token-balances.msw.ts +57 -0
  109. package/openapi-client/generated/evm-token-balances/evm-token-balances.ts +37 -0
  110. package/openapi-client/generated/faucets/faucets.ts +2 -1
  111. package/openapi-client/generated/index.msw.ts +2 -1
  112. package/openapi-client/index.ts +4 -0
  113. package/package.json +2 -3
  114. package/types/misc.ts +39 -0
  115. package/version.ts +1 -1
@@ -1,18 +1,19 @@
1
- import { SendUserOperationReturnType } from "../../actions/evm/sendUserOperation.js";
2
- import { Call, Calls } from "../../types/calls.js";
3
- import { Address, Hex } from "../../types/misc.js";
4
- import { WaitOptions } from "../../utils/wait.js";
5
-
6
- import type {
1
+ import {
7
2
  EvmAccount as Account,
8
3
  EvmServerAccount as ServerAccount,
9
4
  EvmSmartAccount as SmartAccount,
10
5
  } from "../../accounts/types.js";
11
- import type {
6
+ import { SendUserOperationReturnType } from "../../actions/evm/sendUserOperation.js";
7
+ import {
12
8
  EvmUserOperationNetwork,
13
9
  EvmUserOperationStatus,
14
10
  OpenApiEvmMethods,
11
+ ListEvmTokenBalancesNetwork,
12
+ SendEvmTransactionBodyNetwork,
15
13
  } from "../../openapi-client/index.js";
14
+ import { Call, Calls } from "../../types/calls.js";
15
+ import { Address, Hex, TransactionRequestEIP1559 } from "../../types/misc.js";
16
+ import { WaitOptions } from "../../utils/wait.js";
16
17
 
17
18
  /**
18
19
  * The EvmClient type, where all OpenApiEvmMethods methods are wrapped.
@@ -25,15 +26,16 @@ export type EvmClientInterface = Omit<
25
26
  | "getEvmAccountByName" // mapped to getAccount
26
27
  | "getEvmSmartAccount" // mapped to getSmartAccount
27
28
  | "getUserOperation"
28
- | "listEVMBalances" // omit
29
29
  | "listEvmAccounts" // mapped to listAccounts
30
30
  | "listEvmSmartAccounts" // mapped to listSmartAccounts
31
+ | "listEvmTokenBalances" // mapped to listTokenBalances
31
32
  | "prepareUserOperation"
32
33
  | "requestEvmFaucet" // mapped to requestFaucet
33
34
  | "sendUserOperation"
34
35
  | "signEvmHash" // mapped to signHash
35
36
  | "signEvmMessage" // mapped to signMessage
36
37
  | "signEvmTransaction" // mapped to signTransaction
38
+ | "sendEvmTransaction" // mapped to sendTransaction
37
39
  > & {
38
40
  createAccount: (options: CreateServerAccountOptions) => Promise<ServerAccount>;
39
41
  createSmartAccount: (options: CreateSmartAccountOptions) => Promise<SmartAccount>;
@@ -42,8 +44,10 @@ export type EvmClientInterface = Omit<
42
44
  getUserOperation: (options: GetUserOperationOptions) => Promise<UserOperation>;
43
45
  listAccounts: (options: ListServerAccountsOptions) => Promise<ListServerAccountResult>;
44
46
  listSmartAccounts: (options: ListSmartAccountsOptions) => Promise<ListSmartAccountResult>;
47
+ listTokenBalances: (options: ListTokenBalancesOptions) => Promise<ListTokenBalancesResult>;
45
48
  prepareUserOperation: (options: PrepareUserOperationOptions) => Promise<UserOperation>;
46
49
  requestFaucet: (options: RequestFaucetOptions) => Promise<RequestFaucetResult>;
50
+ sendTransaction: (options: SendTransactionOptions) => Promise<TransactionResult>;
47
51
  sendUserOperation: (options: SendUserOperationOptions) => Promise<SendUserOperationReturnType>;
48
52
  signHash: (options: SignHashOptions) => Promise<SignatureResult>;
49
53
  signMessage: (options: SignMessageOptions) => Promise<SignatureResult>;
@@ -230,6 +234,29 @@ export interface RequestFaucetResult {
230
234
  transactionHash: Hex;
231
235
  }
232
236
 
237
+ /**
238
+ * Options for sending an EVM transaction.
239
+ */
240
+ export interface SendTransactionOptions {
241
+ /** The address of the account. */
242
+ address: Address;
243
+ /**
244
+ * The transaction to send. The chainId is ignored in favor of the `network` field.
245
+ *
246
+ * This can be either:
247
+ * - An RLP-encoded transaction to sign and send, as a 0x-prefixed hex string, or
248
+ * - An EIP-1559 transaction request object.
249
+ */
250
+ transaction: Hex | TransactionRequestEIP1559;
251
+ /**
252
+ * The network to send the transaction to.
253
+ * The chainId in the `transaction` field is ignored in favor of this field.
254
+ */
255
+ network: SendEvmTransactionBodyNetwork;
256
+ /** The idempotency key. */
257
+ idempotencyKey?: string;
258
+ }
259
+
233
260
  /**
234
261
  * Options for sending a user operation.
235
262
  */
@@ -290,6 +317,14 @@ export interface SignatureResult {
290
317
  signature: Hex;
291
318
  }
292
319
 
320
+ /**
321
+ * Result of a transaction
322
+ */
323
+ export interface TransactionResult {
324
+ /** The hash of the transaction. */
325
+ transactionHash: Hex;
326
+ }
327
+
293
328
  /**
294
329
  * Options for waiting for a user operation.
295
330
  */
@@ -301,3 +336,73 @@ export interface WaitForUserOperationOptions {
301
336
  /** The wait options. */
302
337
  waitOptions?: WaitOptions;
303
338
  }
339
+
340
+ /**
341
+ * Options for listing EVM token balances.
342
+ */
343
+ export interface ListTokenBalancesOptions {
344
+ /** The address of the account. */
345
+ address: Address;
346
+ /** The network. */
347
+ network: ListEvmTokenBalancesNetwork;
348
+ /** The page size to paginate through the token balances. */
349
+ pageSize?: number;
350
+ /** The page token to paginate through the token balances. */
351
+ pageToken?: string;
352
+ }
353
+
354
+ /**
355
+ * A token on an EVM network, which is either an ERC-20 or a native token (i.e. ETH).
356
+ */
357
+ export interface EvmToken {
358
+ /**
359
+ * The contract address of the token. For Ether, the contract address is 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
360
+ * per EIP-7528. For ERC-20 tokens, this is the contract address where the token is deployed.
361
+ */
362
+ contractAddress: Address;
363
+ /** The network the token is on. */
364
+ network: ListEvmTokenBalancesNetwork;
365
+ /**
366
+ * The symbol of the token, which is optional and non-unique. Note: This field
367
+ * may not be present for most tokens while the API is still under development.
368
+ */
369
+ symbol?: string;
370
+ /**
371
+ * The name of the token, which is optional and non-unique. Note: This field
372
+ * may not be present for most tokens while the API is still under development.
373
+ */
374
+ name?: string;
375
+ }
376
+
377
+ /**
378
+ * A token amount on an EVM network.
379
+ */
380
+ export interface EvmTokenAmount {
381
+ /** The amount of the token in the smallest indivisible unit of the token. */
382
+ amount: bigint;
383
+ /** The number of decimals in the token. */
384
+ decimals: bigint;
385
+ }
386
+
387
+ /**
388
+ * An EVM token balance.
389
+ */
390
+ export interface EvmTokenBalance {
391
+ /** The token. */
392
+ token: EvmToken;
393
+ /** The amount of the token. */
394
+ amount: EvmTokenAmount;
395
+ }
396
+
397
+ /**
398
+ * The result of listing EVM token balances.
399
+ */
400
+ export interface ListTokenBalancesResult {
401
+ /** The token balances. */
402
+ balances: EvmTokenBalance[];
403
+ /**
404
+ * The next page token to paginate through the token balances.
405
+ * If undefined, there are no more token balances to paginate through.
406
+ */
407
+ nextPageToken?: string;
408
+ }
@@ -1,9 +1,15 @@
1
1
  // eslint-disable-next-line import/no-named-as-default
2
- import Axios, { AxiosInstance, AxiosRequestConfig, HttpStatusCode } from "axios";
2
+ import Axios, { AxiosInstance, AxiosRequestConfig } from "axios";
3
3
 
4
- import { APIError, isOpenAPIError, HttpErrorType } from "./errors.js";
5
4
  import { withAuth } from "../auth/hooks/axios/index.js";
6
5
  import { ERROR_DOCS_PAGE_URL } from "../constants.js";
6
+ import {
7
+ isOpenAPIError,
8
+ APIError,
9
+ HttpErrorType,
10
+ UnknownApiError,
11
+ UnknownError,
12
+ } from "./errors.js";
7
13
 
8
14
  /**
9
15
  * The options for the CDP API.
@@ -115,6 +121,15 @@ export const cdpApiClient = async <T>(
115
121
  const response = await axiosInstance(configWithIdempotencyKey);
116
122
  return response.data as T;
117
123
  } catch (error) {
124
+ // eslint-disable-next-line import/no-named-as-default-member
125
+ if (Axios.isAxiosError(error) && !error.response) {
126
+ throw new UnknownApiError(
127
+ HttpErrorType.unknown,
128
+ error.cause instanceof Error ? error.cause.message : error.message,
129
+ error.cause,
130
+ );
131
+ }
132
+
118
133
  // eslint-disable-next-line import/no-named-as-default-member
119
134
  if (Axios.isAxiosError(error) && error.response) {
120
135
  if (isOpenAPIError(error.response.data)) {
@@ -124,6 +139,7 @@ export const cdpApiClient = async <T>(
124
139
  error.response.data.errorMessage,
125
140
  error.response.data.correlationId,
126
141
  error.response.data.errorLink,
142
+ error.cause,
127
143
  );
128
144
  } else {
129
145
  const statusCode = error.response.status;
@@ -135,6 +151,7 @@ export const cdpApiClient = async <T>(
135
151
  "Unauthorized.",
136
152
  undefined,
137
153
  `${ERROR_DOCS_PAGE_URL}#unauthorized`,
154
+ error.cause,
138
155
  );
139
156
  case 404:
140
157
  throw new APIError(
@@ -143,6 +160,7 @@ export const cdpApiClient = async <T>(
143
160
  "API not found.",
144
161
  undefined,
145
162
  `${ERROR_DOCS_PAGE_URL}#not_found`,
163
+ error.cause,
146
164
  );
147
165
  case 502:
148
166
  throw new APIError(
@@ -151,6 +169,7 @@ export const cdpApiClient = async <T>(
151
169
  "Bad gateway.",
152
170
  undefined,
153
171
  `${ERROR_DOCS_PAGE_URL}`,
172
+ error.cause,
154
173
  );
155
174
  case 503:
156
175
  throw new APIError(
@@ -159,6 +178,7 @@ export const cdpApiClient = async <T>(
159
178
  "Service unavailable. Please try again later.",
160
179
  undefined,
161
180
  `${ERROR_DOCS_PAGE_URL}`,
181
+ error.cause,
162
182
  );
163
183
  default:
164
184
  throw new APIError(
@@ -167,29 +187,16 @@ export const cdpApiClient = async <T>(
167
187
  "An unexpected error occurred.",
168
188
  undefined,
169
189
  `${ERROR_DOCS_PAGE_URL}`,
190
+ error.cause,
170
191
  );
171
192
  }
172
193
  }
173
- // eslint-disable-next-line import/no-named-as-default-member
174
- } else if (Axios.isAxiosError(error) && error.request) {
175
- throw new APIError(
176
- HttpStatusCode.ServiceUnavailable,
177
- HttpErrorType.service_unavailable,
178
- "Network error, unable to reach the service.",
179
- undefined,
180
- `${ERROR_DOCS_PAGE_URL}`,
181
- );
182
- } else {
183
- throw new APIError(
184
- HttpStatusCode.InternalServerError,
185
- HttpErrorType.unexpected_error,
186
- error instanceof Error
187
- ? error.message
188
- : `An unexpected error occurred: ${JSON.stringify(error, Object.getOwnPropertyNames(error))}`,
189
- undefined,
190
- `${ERROR_DOCS_PAGE_URL}`,
191
- );
192
194
  }
195
+
196
+ throw new UnknownError(
197
+ "Something went wrong. Please reach out at https://discord.com/channels/1220414409550336183/1271495764580896789 for help.",
198
+ error instanceof Error ? error : undefined,
199
+ );
193
200
  }
194
201
  };
195
202
 
@@ -9,6 +9,7 @@ export const HttpErrorType = {
9
9
  not_found: "not_found",
10
10
  bad_gateway: "bad_gateway",
11
11
  service_unavailable: "service_unavailable",
12
+ unknown: "unknown",
12
13
  } as const;
13
14
 
14
15
  export type HttpErrorType = (typeof HttpErrorType)[keyof typeof HttpErrorType];
@@ -36,6 +37,7 @@ export class APIError extends Error {
36
37
  * @param errorMessage - The error message
37
38
  * @param correlationId - The correlation ID
38
39
  * @param errorLink - URL to documentation about this error
40
+ * @param cause - The cause of the error
39
41
  */
40
42
  constructor(
41
43
  statusCode: number,
@@ -43,8 +45,9 @@ export class APIError extends Error {
43
45
  errorMessage: string,
44
46
  correlationId?: string,
45
47
  errorLink?: string,
48
+ cause?: Error,
46
49
  ) {
47
- super(errorMessage);
50
+ super(errorMessage, { cause });
48
51
  this.name = "APIError";
49
52
  this.statusCode = statusCode;
50
53
  this.errorType = errorType;
@@ -78,6 +81,39 @@ export class APIError extends Error {
78
81
  }
79
82
  }
80
83
 
84
+ /**
85
+ * Error thrown when an Axios request is made but no response is received
86
+ */
87
+ export class UnknownApiError extends APIError {
88
+ /**
89
+ * Constructor for the UnknownApiError class
90
+ *
91
+ * @param errorType - The type of error
92
+ * @param errorMessage - The error message
93
+ * @param cause - The cause of the error
94
+ */
95
+ constructor(errorType: APIErrorType, errorMessage: string, cause?: Error) {
96
+ super(0, errorType, errorMessage, undefined, undefined, cause);
97
+ this.name = "UnknownApiError";
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Error thrown when an error is not known
103
+ */
104
+ export class UnknownError extends Error {
105
+ /**
106
+ * Constructor for the UnknownError class
107
+ *
108
+ * @param message - The error message
109
+ * @param cause - The cause of the error
110
+ */
111
+ constructor(message: string, cause?: Error) {
112
+ super(message, { cause });
113
+ this.name = "UnknownError";
114
+ }
115
+ }
116
+
81
117
  /**
82
118
  * Type guard to check if an object is an OpenAPIError
83
119
  *
@@ -45,6 +45,7 @@ export const ErrorType = {
45
45
  request_canceled: "request_canceled",
46
46
  timed_out: "timed_out",
47
47
  unauthorized: "unauthorized",
48
+ policy_violation: "policy_violation",
48
49
  } as const;
49
50
 
50
51
  /**
@@ -138,6 +139,64 @@ export interface EvmUserOperation {
138
139
  transactionHash?: string;
139
140
  }
140
141
 
142
+ /**
143
+ * The name of the supported EVM networks in human-readable format.
144
+ */
145
+ export type ListEvmTokenBalancesNetwork =
146
+ (typeof ListEvmTokenBalancesNetwork)[keyof typeof ListEvmTokenBalancesNetwork];
147
+
148
+ // eslint-disable-next-line @typescript-eslint/no-redeclare
149
+ export const ListEvmTokenBalancesNetwork = {
150
+ base: "base",
151
+ "base-sepolia": "base-sepolia",
152
+ } as const;
153
+
154
+ /**
155
+ * Amount of a given token.
156
+ */
157
+ export interface TokenAmount {
158
+ /**
159
+ * The amount is denominated in the smallest indivisible unit of the token. For ETH, the smallest indivisible unit is Wei (10^-18 ETH). For ERC-20s, the smallest unit is the unit returned from `function totalSupply() public view returns (uint256)`.
160
+ * @pattern ^[0-9]+$
161
+ */
162
+ amount: string;
163
+ /** 'decimals' is the exponential value N that satisfies the equation `amount * 10^-N = standard_denomination`. The standard denomination is the most commonly used denomination for the token.
164
+ - In the case of the native gas token, `decimals` is defined via convention. As an example, for ETH of Ethereum mainnet, the standard denomination is 10^-18 the smallest denomination (Wei). As such, for ETH on Ethereum mainnet, `decimals` is 18. - In the case of ERC-20 tokens, `decimals` is defined via configuration. `decimals` will be the number returned by `function decimals() public view returns (uint8)` on the underlying token contract.
165
+ Not all tokens have a `decimals` field, as this function is [optional in the ERC-20 specification](https://eips.ethereum.org/EIPS/eip-20#decimals). This field will be left empty if the underlying token contract doesn't implement `decimals`.
166
+ Further, this endpoint will only populate this value for a small subset of whitelisted ERC-20 tokens at this time. We intend to improve coverage in the future. */
167
+ decimals: number;
168
+ }
169
+
170
+ /**
171
+ * General information about a token. Includes the type, the network, and other identifying information.
172
+ */
173
+ export interface Token {
174
+ network: ListEvmTokenBalancesNetwork;
175
+ /** The symbol of this token (ex: SOL, ETH, USDC).
176
+ The token symbol is not unique. It is possible for two different tokens to have the same symbol.
177
+ For native gas tokens, this symbol is defined via convention. As an example, for ETH on Ethereum mainnet, the symbol is "ETH". For ERC-20 tokens, this symbol is defined via configuration. `symbol` will be the string returned by `function symbol() public view returns (string)` on the underlying token contract.
178
+ Not all tokens have a symbol, as this function is [optional in the ERC-20 specification](https://eips.ethereum.org/EIPS/eip-20#symbol). This field will only be populated when the token's underlying ERC-20 contract has a `symbol()` function.
179
+ Further, this endpoint will only populate this value for a small subset of whitelisted ERC-20 tokens at this time. We intend to improve coverage in the future. */
180
+ symbol?: string;
181
+ /** The name of this token (ex: "Solana", "Ether", "USD Coin").
182
+ The token name is not unique. It is possible for two different tokens to have the same name.
183
+ For native gas tokens, this name is defined via convention. As an example, for ETH on Ethereum mainnet, the name is "Ether". For ERC-20 tokens, this name is defined via configuration. `name` will be the string returned by `function name() public view returns (string)` on the underlying token contract.
184
+ Not all tokens have a name, as this function is [optional in the ERC-20 specification](https://eips.ethereum.org/EIPS/eip-20#name). This field will only be populated when the token's underlying ERC-20 contract has a `name()` function.
185
+ Further, this endpoint will only populate this value for a small subset of whitelisted ERC-20 tokens at this time. We intend to improve coverage in the future. */
186
+ name?: string;
187
+ /**
188
+ * The contract address of the token.
189
+ For Ether, the contract address is `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` per [EIP-7528](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7528.md). For ERC-20 tokens, this is the contract address where the token is deployed.
190
+ * @pattern ^0x[0-9a-fA-F]{40}$
191
+ */
192
+ contractAddress: string;
193
+ }
194
+
195
+ export interface TokenBalance {
196
+ amount: TokenAmount;
197
+ token: Token;
198
+ }
199
+
141
200
  export interface SolanaAccount {
142
201
  /**
143
202
  * The base58 encoded Solana address.
@@ -170,7 +229,7 @@ export type AlreadyExistsErrorResponse = Error;
170
229
 
171
230
  /**
172
231
  * A JWT signed using your Wallet Secret, encoded in base64. Refer to the
173
- [Generate a Wallet Token](https://docs.cdp.coinbase.com/api-v2/docs/authentication#3-generate-a-wallet-token)
232
+ [Generate Wallet Token](https://docs.cdp.coinbase.com/api-v2/docs/authentication#2-generate-wallet-token)
174
233
  section of our Authentication docs for more details on how to generate your Wallet Token.
175
234
 
176
235
  */
@@ -212,6 +271,30 @@ Account names must be unique across all EVM accounts in the developer's CDP Proj
212
271
  name?: string;
213
272
  };
214
273
 
274
+ /**
275
+ * The network to send the transaction to.
276
+ */
277
+ export type SendEvmTransactionBodyNetwork =
278
+ (typeof SendEvmTransactionBodyNetwork)[keyof typeof SendEvmTransactionBodyNetwork];
279
+
280
+ // eslint-disable-next-line @typescript-eslint/no-redeclare
281
+ export const SendEvmTransactionBodyNetwork = {
282
+ base: "base",
283
+ "base-sepolia": "base-sepolia",
284
+ } as const;
285
+
286
+ export type SendEvmTransactionBody = {
287
+ /** The network to send the transaction to. */
288
+ network: SendEvmTransactionBodyNetwork;
289
+ /** The RLP-encoded transaction to sign and send, as a 0x-prefixed hex string. */
290
+ transaction: string;
291
+ };
292
+
293
+ export type SendEvmTransaction200 = {
294
+ /** The hash of the transaction, as a 0x-prefixed hex string. */
295
+ transactionHash: string;
296
+ };
297
+
215
298
  export type SignEvmTransactionBody = {
216
299
  /** The RLP-encoded transaction to sign, as a 0x-prefixed hex string. */
217
300
  transaction: string;
@@ -287,10 +370,28 @@ export type PrepareUserOperationBody = {
287
370
  };
288
371
 
289
372
  export type SendUserOperationBody = {
290
- /** The hex-encoded signature of the user operation. */
373
+ /** The hex-encoded signature of the user operation. This should be a 65-byte signature consisting of the `r`, `s`, and `v` values of the ECDSA signature. Note that the `v` value should conform to the `personal_sign` standard, which means it should be 27 or 28. */
291
374
  signature: string;
292
375
  };
293
376
 
377
+ export type ListEvmTokenBalancesParams = {
378
+ /**
379
+ * The number of balances to return per page.
380
+ */
381
+ pageSize?: number;
382
+ /**
383
+ * The token for the next page of balances. Will be empty if there are no more balances to fetch.
384
+ */
385
+ pageToken?: string;
386
+ };
387
+
388
+ export type ListEvmTokenBalances200AllOf = {
389
+ /** The list of EVM token balances. */
390
+ balances: TokenBalance[];
391
+ };
392
+
393
+ export type ListEvmTokenBalances200 = ListEvmTokenBalances200AllOf & ListResponse;
394
+
294
395
  /**
295
396
  * The network to request funds from.
296
397
  */
@@ -12,6 +12,7 @@ import { HttpResponse, delay, http } from "msw";
12
12
  import type {
13
13
  EvmAccount,
14
14
  ListEvmAccounts200,
15
+ SendEvmTransaction200,
15
16
  SignEvmHash200,
16
17
  SignEvmMessage200,
17
18
  SignEvmTransaction200,
@@ -65,6 +66,10 @@ export const getGetEvmAccountByNameResponseMock = (
65
66
  ...overrideResponse,
66
67
  });
67
68
 
69
+ export const getSendEvmTransactionResponseMock = (
70
+ overrideResponse: Partial<SendEvmTransaction200> = {},
71
+ ): SendEvmTransaction200 => ({ transactionHash: faker.string.alpha(20), ...overrideResponse });
72
+
68
73
  export const getSignEvmTransactionResponseMock = (
69
74
  overrideResponse: Partial<SignEvmTransaction200> = {},
70
75
  ): SignEvmTransaction200 => ({ signedTransaction: faker.string.alpha(20), ...overrideResponse });
@@ -163,6 +168,29 @@ export const getGetEvmAccountByNameMockHandler = (
163
168
  });
164
169
  };
165
170
 
171
+ export const getSendEvmTransactionMockHandler = (
172
+ overrideResponse?:
173
+ | SendEvmTransaction200
174
+ | ((
175
+ info: Parameters<Parameters<typeof http.post>[1]>[0],
176
+ ) => Promise<SendEvmTransaction200> | SendEvmTransaction200),
177
+ ) => {
178
+ return http.post("*/v2/evm/accounts/:address/send/transaction", async info => {
179
+ await delay(0);
180
+
181
+ return new HttpResponse(
182
+ JSON.stringify(
183
+ overrideResponse !== undefined
184
+ ? typeof overrideResponse === "function"
185
+ ? await overrideResponse(info)
186
+ : overrideResponse
187
+ : getSendEvmTransactionResponseMock(),
188
+ ),
189
+ { status: 200, headers: { "Content-Type": "application/json" } },
190
+ );
191
+ });
192
+ };
193
+
166
194
  export const getSignEvmTransactionMockHandler = (
167
195
  overrideResponse?:
168
196
  | SignEvmTransaction200
@@ -236,6 +264,7 @@ export const getEvmAccountsMock = () => [
236
264
  getCreateEvmAccountMockHandler(),
237
265
  getGetEvmAccountMockHandler(),
238
266
  getGetEvmAccountByNameMockHandler(),
267
+ getSendEvmTransactionMockHandler(),
239
268
  getSignEvmTransactionMockHandler(),
240
269
  getSignEvmHashMockHandler(),
241
270
  getSignEvmMessageMockHandler(),
@@ -10,6 +10,8 @@ import type {
10
10
  EvmAccount,
11
11
  ListEvmAccounts200,
12
12
  ListEvmAccountsParams,
13
+ SendEvmTransaction200,
14
+ SendEvmTransactionBody,
13
15
  SignEvmHash200,
14
16
  SignEvmHashBody,
15
17
  SignEvmMessage200,
@@ -74,6 +76,50 @@ export const getEvmAccountByName = (
74
76
  options,
75
77
  );
76
78
  };
79
+ /**
80
+ * Signs a transaction with the given EVM account and sends it to the indicated supported network. This API handles nonce management and gas estimation, leaving the developer to provide only the minimal set of fields necessary to send the transaction. The transaction should be serialized as a hex string using [RLP](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/).
81
+
82
+ The transaction must be an [EIP-1559 dynamic fee transaction](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md).
83
+
84
+
85
+ **Transaction fields and API behavior**
86
+
87
+ - `to` *(Required)*: The address of the contract or account to send the transaction to.
88
+ - `chainId` *(Ignored)*: The value of the `chainId` field in the transaction is ignored.
89
+ The transaction will be sent to the network indicated by the `network` field in the request body.
90
+
91
+ - `nonce` *(Optional)*: The nonce to use for the transaction. If not provided, the API will assign
92
+ a nonce to the transaction based on the current state of the account.
93
+
94
+ - `maxPriorityFeePerGas` *(Optional)*: The maximum priority fee per gas to use for the transaction.
95
+ If not provided, the API will estimate a value based on current network conditions.
96
+
97
+ - `maxFeePerGas` *(Optional)*: The maximum fee per gas to use for the transaction.
98
+ If not provided, the API will estimate a value based on current network conditions.
99
+
100
+ - `gasLimit` *(Optional)*: The gas limit to use for the transaction. If not provided, the API will estimate a value
101
+ based on the `to` and `data` fields of the transaction.
102
+
103
+ - `value` *(Optional)*: The amount of ETH, in wei, to send with the transaction.
104
+ - `data` *(Optional)*: The data to send with the transaction; only used for contract calls.
105
+ - `accessList` *(Optional)*: The access list to use for the transaction.
106
+ * @summary Send a transaction
107
+ */
108
+ export const sendEvmTransaction = (
109
+ address: string,
110
+ sendEvmTransactionBody: SendEvmTransactionBody,
111
+ options?: SecondParameter<typeof cdpApiClient>,
112
+ ) => {
113
+ return cdpApiClient<SendEvmTransaction200>(
114
+ {
115
+ url: `/v2/evm/accounts/${address}/send/transaction`,
116
+ method: "POST",
117
+ headers: { "Content-Type": "application/json" },
118
+ data: sendEvmTransactionBody,
119
+ },
120
+ options,
121
+ );
122
+ };
77
123
  /**
78
124
  * Signs a transaction with the given EVM account.
79
125
  The transaction should be serialized as a hex string using [RLP](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/).
@@ -98,9 +144,6 @@ export const signEvmTransaction = (
98
144
  };
99
145
  /**
100
146
  * Signs an arbitrary 32 byte hash with the given EVM account.
101
-
102
-
103
- **WARNING: This API will likely be deprecated in the future.** It is recommended not to depend on it. Never sign a hash that you didn't generate, as it can be an arbitrary transaction. For example, it might send all of your funds to an attacker.
104
147
  * @summary Sign a hash
105
148
  */
106
149
  export const signEvmHash = (
@@ -145,6 +188,7 @@ export type GetEvmAccountResult = NonNullable<Awaited<ReturnType<typeof getEvmAc
145
188
  export type GetEvmAccountByNameResult = NonNullable<
146
189
  Awaited<ReturnType<typeof getEvmAccountByName>>
147
190
  >;
191
+ export type SendEvmTransactionResult = NonNullable<Awaited<ReturnType<typeof sendEvmTransaction>>>;
148
192
  export type SignEvmTransactionResult = NonNullable<Awaited<ReturnType<typeof signEvmTransaction>>>;
149
193
  export type SignEvmHashResult = NonNullable<Awaited<ReturnType<typeof signEvmHash>>>;
150
194
  export type SignEvmMessageResult = NonNullable<Awaited<ReturnType<typeof signEvmMessage>>>;
@@ -99,6 +99,7 @@ export const getUserOperation = (
99
99
  };
100
100
  /**
101
101
  * Sends a user operation with a signature.
102
+ The signature that is sent should be 65 bytes, consisting of the `r`, `s`, and `v` values of the ECDSA signature. Note that the `v` value should conform to the `personal_sign` standard, which means it should be 27 or 28.
102
103
  * @summary Send a user operation
103
104
  */
104
105
  export const sendUserOperation = (
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Generated by orval v7.6.0 🍺
3
+ * Do not edit manually.
4
+ * Coinbase Developer Platform APIs
5
+ * The Coinbase Developer Platform APIs - leading the world's transition onchain.
6
+ * OpenAPI spec version: 2.0.0
7
+ */
8
+ import { faker } from "@faker-js/faker";
9
+
10
+ import { HttpResponse, delay, http } from "msw";
11
+
12
+ import { ListEvmTokenBalancesNetwork } from "../coinbaseDeveloperPlatformAPIs.schemas.js";
13
+ import type { ListEvmTokenBalances200 } from "../coinbaseDeveloperPlatformAPIs.schemas.js";
14
+
15
+ export const getListEvmTokenBalancesResponseMock = (): ListEvmTokenBalances200 => ({
16
+ ...{
17
+ balances: Array.from({ length: faker.number.int({ min: 1, max: 10 }) }, (_, i) => i + 1).map(
18
+ () => ({
19
+ amount: {
20
+ amount: faker.helpers.fromRegExp("^[0-9]+$"),
21
+ decimals: faker.number.int({ min: undefined, max: undefined }),
22
+ },
23
+ token: {
24
+ network: faker.helpers.arrayElement(Object.values(ListEvmTokenBalancesNetwork)),
25
+ symbol: faker.helpers.arrayElement([faker.string.alpha(20), undefined]),
26
+ name: faker.helpers.arrayElement([faker.string.alpha(20), undefined]),
27
+ contractAddress: faker.helpers.fromRegExp("^0x[0-9a-fA-F]{40}$"),
28
+ },
29
+ }),
30
+ ),
31
+ },
32
+ ...{ nextPageToken: faker.helpers.arrayElement([faker.string.alpha(20), undefined]) },
33
+ });
34
+
35
+ export const getListEvmTokenBalancesMockHandler = (
36
+ overrideResponse?:
37
+ | ListEvmTokenBalances200
38
+ | ((
39
+ info: Parameters<Parameters<typeof http.get>[1]>[0],
40
+ ) => Promise<ListEvmTokenBalances200> | ListEvmTokenBalances200),
41
+ ) => {
42
+ return http.get("*/v2/evm/token-balances/:network/:address", async info => {
43
+ await delay(0);
44
+
45
+ return new HttpResponse(
46
+ JSON.stringify(
47
+ overrideResponse !== undefined
48
+ ? typeof overrideResponse === "function"
49
+ ? await overrideResponse(info)
50
+ : overrideResponse
51
+ : getListEvmTokenBalancesResponseMock(),
52
+ ),
53
+ { status: 200, headers: { "Content-Type": "application/json" } },
54
+ );
55
+ });
56
+ };
57
+ export const getEvmTokenBalancesMock = () => [getListEvmTokenBalancesMockHandler()];