@coinbase/cdp-sdk 1.14.0 → 1.16.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 (98) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +113 -20
  3. package/_cjs/accounts/evm/toEvmServerAccount.js +13 -7
  4. package/_cjs/accounts/evm/toEvmServerAccount.js.map +1 -1
  5. package/_cjs/accounts/evm/toEvmSmartAccount.js +18 -0
  6. package/_cjs/accounts/evm/toEvmSmartAccount.js.map +1 -1
  7. package/_cjs/actions/evm/signAndWrapTypedDataForSmartAccount.js +186 -0
  8. package/_cjs/actions/evm/signAndWrapTypedDataForSmartAccount.js.map +1 -0
  9. package/_cjs/actions/evm/swap/createSwapQuote.js +26 -8
  10. package/_cjs/actions/evm/swap/createSwapQuote.js.map +1 -1
  11. package/_cjs/actions/evm/swap/getSwapPrice.js +3 -2
  12. package/_cjs/actions/evm/swap/getSwapPrice.js.map +1 -1
  13. package/_cjs/actions/evm/swap/sendSwapOperation.js +153 -0
  14. package/_cjs/actions/evm/swap/sendSwapOperation.js.map +1 -0
  15. package/_cjs/actions/evm/swap/sendSwapTransaction.js +16 -2
  16. package/_cjs/actions/evm/swap/sendSwapTransaction.js.map +1 -1
  17. package/_cjs/client/evm/evm.js +56 -6
  18. package/_cjs/client/evm/evm.js.map +1 -1
  19. package/_cjs/client/solana/solana.js +43 -0
  20. package/_cjs/client/solana/solana.js.map +1 -1
  21. package/_cjs/utils/export.js +84 -0
  22. package/_cjs/utils/export.js.map +1 -0
  23. package/_cjs/utils/uuidV4.js +26 -0
  24. package/_cjs/utils/uuidV4.js.map +1 -0
  25. package/_cjs/version.js +1 -1
  26. package/_esm/accounts/evm/toEvmServerAccount.js +14 -8
  27. package/_esm/accounts/evm/toEvmServerAccount.js.map +1 -1
  28. package/_esm/accounts/evm/toEvmSmartAccount.js +18 -0
  29. package/_esm/accounts/evm/toEvmSmartAccount.js.map +1 -1
  30. package/_esm/actions/evm/signAndWrapTypedDataForSmartAccount.js +181 -0
  31. package/_esm/actions/evm/signAndWrapTypedDataForSmartAccount.js.map +1 -0
  32. package/_esm/actions/evm/swap/createSwapQuote.js +26 -8
  33. package/_esm/actions/evm/swap/createSwapQuote.js.map +1 -1
  34. package/_esm/actions/evm/swap/getSwapPrice.js +3 -2
  35. package/_esm/actions/evm/swap/getSwapPrice.js.map +1 -1
  36. package/_esm/actions/evm/swap/sendSwapOperation.js +150 -0
  37. package/_esm/actions/evm/swap/sendSwapOperation.js.map +1 -0
  38. package/_esm/actions/evm/swap/sendSwapTransaction.js +16 -2
  39. package/_esm/actions/evm/swap/sendSwapTransaction.js.map +1 -1
  40. package/_esm/client/evm/evm.js +58 -8
  41. package/_esm/client/evm/evm.js.map +1 -1
  42. package/_esm/client/solana/solana.js +43 -0
  43. package/_esm/client/solana/solana.js.map +1 -1
  44. package/_esm/utils/export.js +75 -0
  45. package/_esm/utils/export.js.map +1 -0
  46. package/_esm/utils/uuidV4.js +23 -0
  47. package/_esm/utils/uuidV4.js.map +1 -0
  48. package/_esm/version.js +1 -1
  49. package/_types/accounts/evm/toEvmServerAccount.d.ts.map +1 -1
  50. package/_types/accounts/evm/toEvmSmartAccount.d.ts.map +1 -1
  51. package/_types/accounts/evm/types.d.ts +4 -4
  52. package/_types/accounts/evm/types.d.ts.map +1 -1
  53. package/_types/actions/evm/signAndWrapTypedDataForSmartAccount.d.ts +133 -0
  54. package/_types/actions/evm/signAndWrapTypedDataForSmartAccount.d.ts.map +1 -0
  55. package/_types/actions/evm/swap/createSwapQuote.d.ts.map +1 -1
  56. package/_types/actions/evm/swap/getSwapPrice.d.ts +2 -1
  57. package/_types/actions/evm/swap/getSwapPrice.d.ts.map +1 -1
  58. package/_types/actions/evm/swap/sendSwapOperation.d.ts +64 -0
  59. package/_types/actions/evm/swap/sendSwapOperation.d.ts.map +1 -0
  60. package/_types/actions/evm/swap/sendSwapTransaction.d.ts.map +1 -1
  61. package/_types/actions/evm/swap/types.d.ts +131 -5
  62. package/_types/actions/evm/swap/types.d.ts.map +1 -1
  63. package/_types/actions/evm/types.d.ts +112 -21
  64. package/_types/actions/evm/types.d.ts.map +1 -1
  65. package/_types/client/cdp.d.ts +1 -2
  66. package/_types/client/cdp.d.ts.map +1 -1
  67. package/_types/client/evm/evm.d.ts +29 -3
  68. package/_types/client/evm/evm.d.ts.map +1 -1
  69. package/_types/client/evm/evm.types.d.ts +45 -7
  70. package/_types/client/evm/evm.types.d.ts.map +1 -1
  71. package/_types/client/solana/solana.d.ts +26 -1
  72. package/_types/client/solana/solana.d.ts.map +1 -1
  73. package/_types/client/solana/solana.types.d.ts +12 -0
  74. package/_types/client/solana/solana.types.d.ts.map +1 -1
  75. package/_types/utils/export.d.ts +30 -0
  76. package/_types/utils/export.d.ts.map +1 -0
  77. package/_types/utils/uuidV4.d.ts +10 -0
  78. package/_types/utils/uuidV4.d.ts.map +1 -0
  79. package/_types/version.d.ts +1 -1
  80. package/accounts/evm/toEvmServerAccount.ts +33 -15
  81. package/accounts/evm/toEvmSmartAccount.ts +25 -0
  82. package/accounts/evm/types.ts +14 -6
  83. package/actions/evm/signAndWrapTypedDataForSmartAccount.ts +246 -0
  84. package/actions/evm/swap/createSwapQuote.ts +42 -17
  85. package/actions/evm/swap/getSwapPrice.ts +15 -11
  86. package/actions/evm/swap/sendSwapOperation.ts +182 -0
  87. package/actions/evm/swap/sendSwapTransaction.ts +18 -2
  88. package/actions/evm/swap/types.ts +154 -5
  89. package/actions/evm/types.ts +123 -21
  90. package/client/cdp.ts +1 -1
  91. package/client/evm/evm.ts +101 -33
  92. package/client/evm/evm.types.ts +48 -6
  93. package/client/solana/solana.ts +61 -0
  94. package/client/solana/solana.types.ts +15 -2
  95. package/package.json +1 -1
  96. package/utils/export.ts +89 -0
  97. package/utils/uuidV4.ts +23 -0
  98. package/version.ts +1 -1
package/client/evm/evm.ts CHANGED
@@ -1,51 +1,52 @@
1
- import { publicEncrypt, constants } from "crypto";
1
+ import { constants, publicEncrypt } from "crypto";
2
2
 
3
- import { Address } from "viem";
3
+ import { type Address, getTypesForEIP712Domain } from "viem";
4
4
 
5
5
  import { ImportEvmAccountPublicRSAKey } from "./constants.js";
6
6
  import {
7
7
  CreateServerAccountOptions,
8
- GetServerAccountOptions,
9
- ListServerAccountsOptions,
10
8
  CreateSmartAccountOptions,
11
- WaitForUserOperationOptions,
12
- SignHashOptions,
13
- SignatureResult,
14
- SignMessageOptions,
15
- SignTransactionOptions,
16
- GetSmartAccountOptions,
17
- SmartAccount,
18
- ServerAccount,
9
+ CreateSwapQuoteOptions,
10
+ CreateSwapQuoteResult,
19
11
  EvmClientInterface,
20
- ListServerAccountResult,
21
- PrepareUserOperationOptions,
22
- UserOperation,
12
+ ExportServerAccountOptions,
13
+ GetOrCreateServerAccountOptions,
14
+ GetOrCreateSmartAccountOptions,
15
+ GetServerAccountOptions,
16
+ GetSmartAccountOptions,
17
+ GetSwapPriceOptions,
18
+ GetSwapPriceResult,
23
19
  GetUserOperationOptions,
20
+ ImportServerAccountOptions,
21
+ ListServerAccountResult,
22
+ ListServerAccountsOptions,
24
23
  ListSmartAccountResult,
25
24
  ListSmartAccountsOptions,
26
- GetOrCreateServerAccountOptions,
25
+ PrepareUserOperationOptions,
26
+ ServerAccount,
27
+ SignatureResult,
28
+ SignHashOptions,
29
+ SignMessageOptions,
30
+ SignTransactionOptions,
27
31
  SignTypedDataOptions,
28
- UpdateEvmAccountOptions,
29
- ImportServerAccountOptions,
30
- GetSwapPriceOptions,
31
- CreateSwapQuoteOptions,
32
- GetSwapPriceResult,
33
- CreateSwapQuoteResult,
32
+ SmartAccount,
34
33
  SwapUnavailableResult,
35
- GetOrCreateSmartAccountOptions,
34
+ UpdateEvmAccountOptions,
35
+ UserOperation,
36
+ WaitForUserOperationOptions,
36
37
  } from "./evm.types.js";
37
38
  import { toEvmServerAccount } from "../../accounts/evm/toEvmServerAccount.js";
38
39
  import { toEvmSmartAccount } from "../../accounts/evm/toEvmSmartAccount.js";
39
40
  import { getUserOperation } from "../../actions/evm/getUserOperation.js";
40
41
  import {
41
42
  listTokenBalances,
42
- ListTokenBalancesResult,
43
43
  ListTokenBalancesOptions,
44
+ ListTokenBalancesResult,
44
45
  } from "../../actions/evm/listTokenBalances.js";
45
46
  import {
47
+ requestFaucet,
46
48
  RequestFaucetOptions,
47
49
  RequestFaucetResult,
48
- requestFaucet,
49
50
  } from "../../actions/evm/requestFaucet.js";
50
51
  import { sendTransaction } from "../../actions/evm/sendTransaction.js";
51
52
  import {
@@ -61,12 +62,16 @@ import {
61
62
  } from "../../actions/evm/waitForUserOperation.js";
62
63
  import { Analytics } from "../../analytics.js";
63
64
  import { APIError } from "../../openapi-client/errors.js";
64
- import { CdpOpenApiClient } from "../../openapi-client/index.js";
65
+ import {
66
+ CdpOpenApiClient,
67
+ EIP712Message as OpenAPIEIP712Message,
68
+ } from "../../openapi-client/index.js";
65
69
  import { Hex } from "../../types/misc.js";
70
+ import { decryptWithPrivateKey, generateExportEncryptionKeyPair } from "../../utils/export.js";
66
71
 
67
72
  import type {
68
- TransactionResult,
69
73
  SendTransactionOptions,
74
+ TransactionResult,
70
75
  } from "../../actions/evm/sendTransaction.js";
71
76
 
72
77
  /**
@@ -213,6 +218,61 @@ export class EvmClient implements EvmClientInterface {
213
218
  }
214
219
  }
215
220
 
221
+ /**
222
+ * Exports a CDP EVM account's private key.
223
+ * It is important to store the private key in a secure place after it's exported.
224
+ *
225
+ * @param {ExportServerAccountOptions} options - Parameters for exporting the account.
226
+ * @param {string} [options.address] - The address of the account to export.
227
+ * @param {string} [options.name] - The name of the account to export.
228
+ * @param {string} [options.idempotencyKey] - An idempotency key.
229
+ *
230
+ * @returns A promise that resolves to the exported account’s 32-byte private key as a hex string, without the "0x" prefix.
231
+ *
232
+ * @example **With an address**
233
+ * ```ts
234
+ * const privateKey = await cdp.evm.exportAccount({
235
+ * address: "0x1234567890123456789012345678901234567890",
236
+ * });
237
+ * ```
238
+ *
239
+ * @example **With a name**
240
+ * ```ts
241
+ * const privateKey = await cdp.evm.exportAccount({
242
+ * name: "MyAccount",
243
+ * });
244
+ * ```
245
+ */
246
+ async exportAccount(options: ExportServerAccountOptions): Promise<string> {
247
+ const { publicKey, privateKey } = await generateExportEncryptionKeyPair();
248
+
249
+ const { encryptedPrivateKey } = await (async () => {
250
+ if (options.address) {
251
+ return CdpOpenApiClient.exportEvmAccount(
252
+ options.address,
253
+ {
254
+ exportEncryptionKey: publicKey,
255
+ },
256
+ options.idempotencyKey,
257
+ );
258
+ }
259
+
260
+ if (options.name) {
261
+ return CdpOpenApiClient.exportEvmAccountByName(
262
+ options.name,
263
+ {
264
+ exportEncryptionKey: publicKey,
265
+ },
266
+ options.idempotencyKey,
267
+ );
268
+ }
269
+
270
+ throw new Error("Either address or name must be provided");
271
+ })();
272
+
273
+ return decryptWithPrivateKey(privateKey, encryptedPrivateKey);
274
+ }
275
+
216
276
  /**
217
277
  * Creates a new CDP EVM smart account.
218
278
  *
@@ -921,14 +981,22 @@ export class EvmClient implements EvmClientInterface {
921
981
  * ```
922
982
  */
923
983
  async signTypedData(options: SignTypedDataOptions): Promise<SignatureResult> {
984
+ const { domain, message, primaryType } = options;
985
+ const types = {
986
+ EIP712Domain: getTypesForEIP712Domain({ domain }),
987
+ ...options.types,
988
+ };
989
+
990
+ const openApiMessage: OpenAPIEIP712Message = {
991
+ domain,
992
+ types,
993
+ primaryType,
994
+ message,
995
+ };
996
+
924
997
  const signature = await CdpOpenApiClient.signEvmTypedData(
925
998
  options.address,
926
- {
927
- domain: options.domain,
928
- types: options.types,
929
- primaryType: options.primaryType,
930
- message: options.message,
931
- },
999
+ openApiMessage,
932
1000
  options.idempotencyKey,
933
1001
  );
934
1002
 
@@ -36,6 +36,8 @@ export type EvmClientInterface = Omit<
36
36
  | "createEvmAccount" // mapped to createAccount
37
37
  | "createEvmSmartAccount" // mapped to createSmartAccount
38
38
  | "importEvmAccount" // mapped to importAccount
39
+ | "exportEvmAccount" // mapped to exportAccount
40
+ | "exportEvmAccountByName" // mapped to exportAccount
39
41
  | "getEvmAccount" // mapped to getAccount
40
42
  | "getEvmAccountByName" // mapped to getAccount
41
43
  | "getEvmSmartAccount" // mapped to getSmartAccount
@@ -63,6 +65,7 @@ export type EvmClientInterface = Omit<
63
65
  createAccount: (options: CreateServerAccountOptions) => Promise<ServerAccount>;
64
66
  createSmartAccount: (options: CreateSmartAccountOptions) => Promise<SmartAccount>;
65
67
  importAccount: (options: ImportServerAccountOptions) => Promise<ServerAccount>;
68
+ exportAccount: (options: ExportServerAccountOptions) => Promise<string>;
66
69
  getAccount: (options: GetServerAccountOptions) => Promise<ServerAccount>;
67
70
  getSmartAccount: (options: GetSmartAccountOptions) => Promise<SmartAccount>;
68
71
  getSwapPrice: (
@@ -103,14 +106,18 @@ export interface CreateSwapQuoteOptions {
103
106
  fromToken: Address;
104
107
  /** The amount to send in atomic units of the token. */
105
108
  fromAmount: bigint;
106
- /** The address that will perform the swap. */
107
- taker?: Address;
108
- /** The signer address (only needed if taker is a smart contract). */
109
+ /** The address receiving the output of the swap. */
110
+ taker: Address;
111
+ /** The address signing the swap (only needed if taker is a smart contract, i.e. for smart account swaps). */
109
112
  signerAddress?: Address;
110
- /** The gas price in Wei. */
113
+ /** The smart account object (required for smart account execution context only). */
114
+ smartAccount?: SmartAccount;
115
+ /** The price per unit of gas in wei. */
111
116
  gasPrice?: bigint;
112
117
  /** The slippage tolerance in basis points (0-10000). */
113
118
  slippageBps?: number;
119
+ /** The idempotency key. */
120
+ idempotencyKey?: string;
114
121
  }
115
122
 
116
123
  /**
@@ -133,6 +140,8 @@ export interface GetSwapPriceOptions {
133
140
  gasPrice?: bigint;
134
141
  /** The slippage tolerance in basis points (0-10000). */
135
142
  slippageBps?: number;
143
+ /** The idempotency key. */
144
+ idempotencyKey?: string;
136
145
  }
137
146
 
138
147
  /**
@@ -183,8 +192,14 @@ export interface ExecuteSwapQuoteOptions {
183
192
  * Result of executing a swap quote.
184
193
  */
185
194
  export interface ExecuteSwapQuoteResult {
186
- /** The transaction hash of the executed swap. */
187
- transactionHash: Hex;
195
+ /** The transaction hash of the executed swap (for EOA swaps). */
196
+ transactionHash?: Hex;
197
+ /** The user operation hash of the executed swap (for smart account swaps). */
198
+ userOpHash?: Hex;
199
+ /** The address of the smart account (for smart account swaps). */
200
+ smartAccountAddress?: Address;
201
+ /** The status of the user operation (for smart accounts swaps). */
202
+ status?: typeof EvmUserOperationStatus.broadcast;
188
203
  }
189
204
 
190
205
  /**
@@ -324,6 +339,18 @@ export interface ImportServerAccountOptions {
324
339
  privateKey: Hex;
325
340
  }
326
341
 
342
+ /**
343
+ * Options for exporting an EVM server account.
344
+ */
345
+ export interface ExportServerAccountOptions {
346
+ /** The address of the account. */
347
+ address?: Address;
348
+ /** The name of the account. */
349
+ name?: string;
350
+ /** The idempotency key. */
351
+ idempotencyKey?: string;
352
+ }
353
+
327
354
  /**
328
355
  * Options for getting an EVM account.
329
356
  */
@@ -584,3 +611,18 @@ export type GetSwapQuoteOptions = GetSwapPriceOptions;
584
611
  export type GetSwapQuoteResult = GetSwapPriceResult;
585
612
  export type SwapQuoteUnavailableResult = SwapUnavailableResult;
586
613
  export type SwapPriceUnavailableResult = SwapUnavailableResult;
614
+
615
+ /**
616
+ * Options for signing and wrapping EIP-712 typed data with a smart account.
617
+ * This method handles the full smart account signature flow including replay-safe hashing.
618
+ */
619
+ export interface SmartAccountSignAndWrapTypedDataOptions {
620
+ /** The chain ID for the signature (used for replay protection). */
621
+ chainId: bigint;
622
+ /** The EIP-712 typed data message to sign. */
623
+ typedData: EIP712Message;
624
+ /** The index of the owner to sign with (defaults to 0). */
625
+ ownerIndex?: bigint;
626
+ /** Optional idempotency key for the signing request. */
627
+ idempotencyKey?: string;
628
+ }
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  CreateAccountOptions,
3
+ ExportAccountOptions,
3
4
  GetAccountOptions,
4
5
  GetOrCreateAccountOptions,
5
6
  ListAccountsOptions,
@@ -19,6 +20,11 @@ import { signTransaction } from "../../actions/solana/signTransaction.js";
19
20
  import { Analytics } from "../../analytics.js";
20
21
  import { APIError } from "../../openapi-client/errors.js";
21
22
  import { CdpOpenApiClient } from "../../openapi-client/index.js";
23
+ import {
24
+ decryptWithPrivateKey,
25
+ formatSolanaPrivateKey,
26
+ generateExportEncryptionKeyPair,
27
+ } from "../../utils/export.js";
22
28
 
23
29
  /**
24
30
  * The namespace containing all Solana methods.
@@ -72,6 +78,61 @@ export class SolanaClient implements SolanaClientInterface {
72
78
  return account;
73
79
  }
74
80
 
81
+ /**
82
+ * Exports a CDP Solana account's private key.
83
+ * It is important to store the private key in a secure place after it's exported.
84
+ *
85
+ * @param {ExportAccountOptions} options - Parameters for exporting the Solana account.
86
+ * @param {string} [options.address] - The address of the account.
87
+ * @param {string} [options.name] - The name of the account.
88
+ *
89
+ * @returns A promise that resolves to the exported account's full 64-byte private key as a base58 encoded string.
90
+ *
91
+ * @example **With an address**
92
+ * ```ts
93
+ * const privateKey = await cdp.solana.exportAccount({
94
+ * address: "1234567890123456789012345678901234567890",
95
+ * });
96
+ * ```
97
+ *
98
+ * @example **With a name**
99
+ * ```ts
100
+ * const privateKey = await cdp.solana.exportAccount({
101
+ * name: "MyAccount",
102
+ * });
103
+ * ```
104
+ */
105
+ async exportAccount(options: ExportAccountOptions): Promise<string> {
106
+ const { publicKey, privateKey } = await generateExportEncryptionKeyPair();
107
+
108
+ const { encryptedPrivateKey } = await (async () => {
109
+ if (options.address) {
110
+ return CdpOpenApiClient.exportSolanaAccount(
111
+ options.address,
112
+ {
113
+ exportEncryptionKey: publicKey,
114
+ },
115
+ options.idempotencyKey,
116
+ );
117
+ }
118
+
119
+ if (options.name) {
120
+ return CdpOpenApiClient.exportSolanaAccountByName(
121
+ options.name,
122
+ {
123
+ exportEncryptionKey: publicKey,
124
+ },
125
+ options.idempotencyKey,
126
+ );
127
+ }
128
+
129
+ throw new Error("Either address or name must be provided");
130
+ })();
131
+
132
+ const decryptedPrivateKey = decryptWithPrivateKey(privateKey, encryptedPrivateKey);
133
+ return formatSolanaPrivateKey(decryptedPrivateKey);
134
+ }
135
+
75
136
  /**
76
137
  * Gets a Solana account by its address.
77
138
  *
@@ -15,10 +15,11 @@ export type SolanaClientInterface = Omit<
15
15
  | "signSolanaMessage" // mapped to signMessage
16
16
  | "signSolanaTransaction" // mapped to signTransaction
17
17
  | "updateSolanaAccount" // mapped to updateAccount
18
- | "exportSolanaAccount"
19
- | "exportSolanaAccountByName"
18
+ | "exportSolanaAccount" // mapped to exportAccount
19
+ | "exportSolanaAccountByName" // mapped to exportAccount
20
20
  > & {
21
21
  createAccount: (options: CreateAccountOptions) => Promise<Account>;
22
+ exportAccount: (options: ExportAccountOptions) => Promise<string>;
22
23
  getAccount: (options: GetAccountOptions) => Promise<Account>;
23
24
  getOrCreateAccount: (options: GetOrCreateAccountOptions) => Promise<Account>;
24
25
  updateAccount: (options: UpdateSolanaAccountOptions) => Promise<Account>;
@@ -48,6 +49,18 @@ export interface CreateAccountOptions {
48
49
  idempotencyKey?: string;
49
50
  }
50
51
 
52
+ /**
53
+ * Options for exporting a Solana account.
54
+ */
55
+ export interface ExportAccountOptions {
56
+ /** The address of the account. */
57
+ address?: string;
58
+ /** The name of the account. */
59
+ name?: string;
60
+ /** The idempotency key. */
61
+ idempotencyKey?: string;
62
+ }
63
+
51
64
  /**
52
65
  * Options for getting a Solana account.
53
66
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinbase/cdp-sdk",
3
- "version": "1.14.0",
3
+ "version": "1.16.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,89 @@
1
+ import { generateKeyPair, privateDecrypt, constants, createPrivateKey } from "crypto";
2
+
3
+ import { Keypair } from "@solana/web3.js";
4
+ import bs58 from "bs58";
5
+
6
+ /**
7
+ * Generates a new RSA key pair with 4096-bit private key.
8
+ * - Private key in PKCS1 DER format
9
+ * - Public key in PKIX/SPKI DER format
10
+ *
11
+ * @returns A promise that resolves to the generated key pair, or rejects with an error.
12
+ */
13
+ export const generateExportEncryptionKeyPair = async () => {
14
+ return await new Promise<{
15
+ publicKey: string;
16
+ privateKey: string;
17
+ }>((resolve, reject) => {
18
+ generateKeyPair(
19
+ "rsa",
20
+ {
21
+ modulusLength: 4096,
22
+ publicKeyEncoding: {
23
+ type: "spki",
24
+ format: "der",
25
+ },
26
+ privateKeyEncoding: {
27
+ type: "pkcs1",
28
+ format: "der",
29
+ },
30
+ },
31
+ (err, publicKey, privateKey) => {
32
+ if (err) {
33
+ reject(err);
34
+ }
35
+ resolve({
36
+ publicKey: publicKey.toString("base64"),
37
+ privateKey: privateKey.toString("base64"),
38
+ });
39
+ },
40
+ );
41
+ });
42
+ };
43
+
44
+ /**
45
+ * Decrypts a ciphertext using RSA-OAEP-SHA256.
46
+ * - Parses PKCS1 private key
47
+ * - Uses RSA-OAEP-SHA256 for decryption
48
+ * - Returns hex-encoded result
49
+ *
50
+ * @param b64PrivateKey - The base64-encoded private key in PKCS1 DER format.
51
+ * @param b64Cipher - The base64-encoded ciphertext.
52
+ * @returns The decrypted key hex string, or throws an error if decryption fails.
53
+ */
54
+ export const decryptWithPrivateKey = (b64PrivateKey: string, b64Cipher: string): string => {
55
+ try {
56
+ // Create a private key object from the PKCS1 DER format
57
+ const privateKey = createPrivateKey({
58
+ key: Buffer.from(b64PrivateKey, "base64"),
59
+ format: "der",
60
+ type: "pkcs1",
61
+ });
62
+
63
+ const decryptedBuffer = privateDecrypt(
64
+ {
65
+ key: privateKey,
66
+ padding: constants.RSA_PKCS1_OAEP_PADDING,
67
+ oaepHash: "sha256",
68
+ },
69
+ Buffer.from(b64Cipher, "base64"),
70
+ );
71
+
72
+ return decryptedBuffer.toString("hex");
73
+ } catch (error) {
74
+ throw new Error(`Decryption failed: ${String(error)}`);
75
+ }
76
+ };
77
+
78
+ /**
79
+ * Format a private key to a base58 string for easy import into Solana wallet apps.
80
+ *
81
+ * @param privateKey - The private key as a hex string
82
+ * @returns The formatted private key as a base58 string
83
+ */
84
+ export const formatSolanaPrivateKey = (privateKey: string): string => {
85
+ const privateKeyBytes = Buffer.from(privateKey, "hex");
86
+ const keypair = Keypair.fromSeed(privateKeyBytes);
87
+ const fullKey = Buffer.concat([keypair.secretKey.subarray(0, 32), keypair.publicKey.toBytes()]);
88
+ return bs58.encode(fullKey);
89
+ };
@@ -0,0 +1,23 @@
1
+ import { createHash } from "crypto";
2
+
3
+ /**
4
+ * Deterministically generates a UUIDv4 from a given input string.
5
+ * This is necessary when we need to generate downstream idempotency keys for operations that have multiple calls.
6
+ *
7
+ * @param input - The input string to derive from
8
+ * @param salt - Optional salt to append to the input (defaults to "salt")
9
+ * @returns A UUIDv4 formatted string
10
+ */
11
+ export function createDeterministicUuidV4(input: string, salt = "salt"): string {
12
+ const hash = createHash("sha256")
13
+ .update(input + "-" + salt)
14
+ .digest("hex");
15
+ // Format as UUIDv4: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
16
+ return [
17
+ hash.slice(0, 8),
18
+ hash.slice(8, 12),
19
+ "4" + hash.slice(13, 16), // Version 4
20
+ ((parseInt(hash.slice(16, 17), 16) & 0x3) | 0x8).toString(16) + hash.slice(17, 20), // Variant bits
21
+ hash.slice(20, 32),
22
+ ].join("-");
23
+ }
package/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = "1.14.0";
1
+ export const version = "1.16.0";