@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.
- package/CHANGELOG.md +20 -0
- package/README.md +113 -20
- package/_cjs/accounts/evm/toEvmServerAccount.js +13 -7
- package/_cjs/accounts/evm/toEvmServerAccount.js.map +1 -1
- package/_cjs/accounts/evm/toEvmSmartAccount.js +18 -0
- package/_cjs/accounts/evm/toEvmSmartAccount.js.map +1 -1
- package/_cjs/actions/evm/signAndWrapTypedDataForSmartAccount.js +186 -0
- package/_cjs/actions/evm/signAndWrapTypedDataForSmartAccount.js.map +1 -0
- package/_cjs/actions/evm/swap/createSwapQuote.js +26 -8
- package/_cjs/actions/evm/swap/createSwapQuote.js.map +1 -1
- package/_cjs/actions/evm/swap/getSwapPrice.js +3 -2
- package/_cjs/actions/evm/swap/getSwapPrice.js.map +1 -1
- package/_cjs/actions/evm/swap/sendSwapOperation.js +153 -0
- package/_cjs/actions/evm/swap/sendSwapOperation.js.map +1 -0
- package/_cjs/actions/evm/swap/sendSwapTransaction.js +16 -2
- package/_cjs/actions/evm/swap/sendSwapTransaction.js.map +1 -1
- package/_cjs/client/evm/evm.js +56 -6
- package/_cjs/client/evm/evm.js.map +1 -1
- package/_cjs/client/solana/solana.js +43 -0
- package/_cjs/client/solana/solana.js.map +1 -1
- package/_cjs/utils/export.js +84 -0
- package/_cjs/utils/export.js.map +1 -0
- package/_cjs/utils/uuidV4.js +26 -0
- package/_cjs/utils/uuidV4.js.map +1 -0
- package/_cjs/version.js +1 -1
- package/_esm/accounts/evm/toEvmServerAccount.js +14 -8
- package/_esm/accounts/evm/toEvmServerAccount.js.map +1 -1
- package/_esm/accounts/evm/toEvmSmartAccount.js +18 -0
- package/_esm/accounts/evm/toEvmSmartAccount.js.map +1 -1
- package/_esm/actions/evm/signAndWrapTypedDataForSmartAccount.js +181 -0
- package/_esm/actions/evm/signAndWrapTypedDataForSmartAccount.js.map +1 -0
- package/_esm/actions/evm/swap/createSwapQuote.js +26 -8
- package/_esm/actions/evm/swap/createSwapQuote.js.map +1 -1
- package/_esm/actions/evm/swap/getSwapPrice.js +3 -2
- package/_esm/actions/evm/swap/getSwapPrice.js.map +1 -1
- package/_esm/actions/evm/swap/sendSwapOperation.js +150 -0
- package/_esm/actions/evm/swap/sendSwapOperation.js.map +1 -0
- package/_esm/actions/evm/swap/sendSwapTransaction.js +16 -2
- package/_esm/actions/evm/swap/sendSwapTransaction.js.map +1 -1
- package/_esm/client/evm/evm.js +58 -8
- package/_esm/client/evm/evm.js.map +1 -1
- package/_esm/client/solana/solana.js +43 -0
- package/_esm/client/solana/solana.js.map +1 -1
- package/_esm/utils/export.js +75 -0
- package/_esm/utils/export.js.map +1 -0
- package/_esm/utils/uuidV4.js +23 -0
- package/_esm/utils/uuidV4.js.map +1 -0
- package/_esm/version.js +1 -1
- package/_types/accounts/evm/toEvmServerAccount.d.ts.map +1 -1
- package/_types/accounts/evm/toEvmSmartAccount.d.ts.map +1 -1
- package/_types/accounts/evm/types.d.ts +4 -4
- package/_types/accounts/evm/types.d.ts.map +1 -1
- package/_types/actions/evm/signAndWrapTypedDataForSmartAccount.d.ts +133 -0
- package/_types/actions/evm/signAndWrapTypedDataForSmartAccount.d.ts.map +1 -0
- package/_types/actions/evm/swap/createSwapQuote.d.ts.map +1 -1
- package/_types/actions/evm/swap/getSwapPrice.d.ts +2 -1
- package/_types/actions/evm/swap/getSwapPrice.d.ts.map +1 -1
- package/_types/actions/evm/swap/sendSwapOperation.d.ts +64 -0
- package/_types/actions/evm/swap/sendSwapOperation.d.ts.map +1 -0
- package/_types/actions/evm/swap/sendSwapTransaction.d.ts.map +1 -1
- package/_types/actions/evm/swap/types.d.ts +131 -5
- package/_types/actions/evm/swap/types.d.ts.map +1 -1
- package/_types/actions/evm/types.d.ts +112 -21
- package/_types/actions/evm/types.d.ts.map +1 -1
- package/_types/client/cdp.d.ts +1 -2
- package/_types/client/cdp.d.ts.map +1 -1
- package/_types/client/evm/evm.d.ts +29 -3
- package/_types/client/evm/evm.d.ts.map +1 -1
- package/_types/client/evm/evm.types.d.ts +45 -7
- package/_types/client/evm/evm.types.d.ts.map +1 -1
- package/_types/client/solana/solana.d.ts +26 -1
- package/_types/client/solana/solana.d.ts.map +1 -1
- package/_types/client/solana/solana.types.d.ts +12 -0
- package/_types/client/solana/solana.types.d.ts.map +1 -1
- package/_types/utils/export.d.ts +30 -0
- package/_types/utils/export.d.ts.map +1 -0
- package/_types/utils/uuidV4.d.ts +10 -0
- package/_types/utils/uuidV4.d.ts.map +1 -0
- package/_types/version.d.ts +1 -1
- package/accounts/evm/toEvmServerAccount.ts +33 -15
- package/accounts/evm/toEvmSmartAccount.ts +25 -0
- package/accounts/evm/types.ts +14 -6
- package/actions/evm/signAndWrapTypedDataForSmartAccount.ts +246 -0
- package/actions/evm/swap/createSwapQuote.ts +42 -17
- package/actions/evm/swap/getSwapPrice.ts +15 -11
- package/actions/evm/swap/sendSwapOperation.ts +182 -0
- package/actions/evm/swap/sendSwapTransaction.ts +18 -2
- package/actions/evm/swap/types.ts +154 -5
- package/actions/evm/types.ts +123 -21
- package/client/cdp.ts +1 -1
- package/client/evm/evm.ts +101 -33
- package/client/evm/evm.types.ts +48 -6
- package/client/solana/solana.ts +61 -0
- package/client/solana/solana.types.ts +15 -2
- package/package.json +1 -1
- package/utils/export.ts +89 -0
- package/utils/uuidV4.ts +23 -0
- package/version.ts +1 -1
package/client/evm/evm.ts
CHANGED
|
@@ -1,51 +1,52 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
SignatureResult,
|
|
14
|
-
SignMessageOptions,
|
|
15
|
-
SignTransactionOptions,
|
|
16
|
-
GetSmartAccountOptions,
|
|
17
|
-
SmartAccount,
|
|
18
|
-
ServerAccount,
|
|
9
|
+
CreateSwapQuoteOptions,
|
|
10
|
+
CreateSwapQuoteResult,
|
|
19
11
|
EvmClientInterface,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
25
|
+
PrepareUserOperationOptions,
|
|
26
|
+
ServerAccount,
|
|
27
|
+
SignatureResult,
|
|
28
|
+
SignHashOptions,
|
|
29
|
+
SignMessageOptions,
|
|
30
|
+
SignTransactionOptions,
|
|
27
31
|
SignTypedDataOptions,
|
|
28
|
-
|
|
29
|
-
ImportServerAccountOptions,
|
|
30
|
-
GetSwapPriceOptions,
|
|
31
|
-
CreateSwapQuoteOptions,
|
|
32
|
-
GetSwapPriceResult,
|
|
33
|
-
CreateSwapQuoteResult,
|
|
32
|
+
SmartAccount,
|
|
34
33
|
SwapUnavailableResult,
|
|
35
|
-
|
|
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 {
|
|
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
|
|
package/client/evm/evm.types.ts
CHANGED
|
@@ -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
|
|
107
|
-
taker
|
|
108
|
-
/** The
|
|
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
|
|
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
|
|
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
|
+
}
|
package/client/solana/solana.ts
CHANGED
|
@@ -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
package/utils/export.ts
ADDED
|
@@ -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
|
+
};
|
package/utils/uuidV4.ts
ADDED
|
@@ -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.
|
|
1
|
+
export const version = "1.16.0";
|