@coinbase/cdp-sdk 1.9.0 → 1.11.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 +14 -0
- package/README.md +28 -0
- package/_cjs/accounts/evm/toEvmServerAccount.js +18 -0
- 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/fund/Quote.js +63 -0
- package/_cjs/actions/evm/fund/Quote.js.map +1 -0
- package/_cjs/actions/evm/fund/fund.js +49 -0
- package/_cjs/actions/evm/fund/fund.js.map +1 -0
- package/_cjs/actions/evm/fund/quoteFund.js +46 -0
- package/_cjs/actions/evm/fund/quoteFund.js.map +1 -0
- package/_cjs/actions/evm/fund/types.js +3 -0
- package/_cjs/actions/evm/fund/types.js.map +1 -0
- package/_cjs/actions/evm/fund/waitForFundOperationReceipt.js +64 -0
- package/_cjs/actions/evm/fund/waitForFundOperationReceipt.js.map +1 -0
- package/_cjs/client/evm/constants.js +21 -0
- package/_cjs/client/evm/constants.js.map +1 -0
- package/_cjs/client/evm/evm.js +76 -0
- package/_cjs/client/evm/evm.js.map +1 -1
- package/_cjs/client/solana/solana.js +4 -1
- package/_cjs/client/solana/solana.js.map +1 -1
- package/_cjs/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js +40 -1
- package/_cjs/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js.map +1 -1
- package/_cjs/openapi-client/generated/evm-accounts/evm-accounts.js +14 -1
- package/_cjs/openapi-client/generated/evm-accounts/evm-accounts.js.map +1 -1
- package/_cjs/openapi-client/generated/evm-accounts/evm-accounts.msw.js +26 -1
- package/_cjs/openapi-client/generated/evm-accounts/evm-accounts.msw.js.map +1 -1
- package/_cjs/openapi-client/generated/index.msw.js +4 -3
- package/_cjs/openapi-client/generated/index.msw.js.map +1 -1
- package/_cjs/openapi-client/generated/payments-alpha/payments-alpha.js +50 -0
- package/_cjs/openapi-client/generated/payments-alpha/payments-alpha.js.map +1 -0
- package/_cjs/openapi-client/generated/payments-alpha/payments-alpha.msw.js +270 -0
- package/_cjs/openapi-client/generated/payments-alpha/payments-alpha.msw.js.map +1 -0
- package/_cjs/openapi-client/index.js +3 -0
- package/_cjs/openapi-client/index.js.map +1 -1
- package/_cjs/version.js +1 -1
- package/_cjs/version.js.map +1 -1
- package/_esm/accounts/evm/toEvmServerAccount.js +18 -0
- 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/fund/Quote.js +59 -0
- package/_esm/actions/evm/fund/Quote.js.map +1 -0
- package/_esm/actions/evm/fund/fund.js +46 -0
- package/_esm/actions/evm/fund/fund.js.map +1 -0
- package/_esm/actions/evm/fund/quoteFund.js +43 -0
- package/_esm/actions/evm/fund/quoteFund.js.map +1 -0
- package/_esm/actions/evm/fund/types.js +2 -0
- package/_esm/actions/evm/fund/types.js.map +1 -0
- package/_esm/actions/evm/fund/waitForFundOperationReceipt.js +61 -0
- package/_esm/actions/evm/fund/waitForFundOperationReceipt.js.map +1 -0
- package/_esm/client/evm/constants.js +18 -0
- package/_esm/client/evm/constants.js.map +1 -0
- package/_esm/client/evm/evm.js +76 -0
- package/_esm/client/evm/evm.js.map +1 -1
- package/_esm/client/solana/solana.js +4 -1
- package/_esm/client/solana/solana.js.map +1 -1
- package/_esm/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js +39 -0
- package/_esm/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.js.map +1 -1
- package/_esm/openapi-client/generated/evm-accounts/evm-accounts.js +12 -0
- package/_esm/openapi-client/generated/evm-accounts/evm-accounts.js.map +1 -1
- package/_esm/openapi-client/generated/evm-accounts/evm-accounts.msw.js +23 -0
- package/_esm/openapi-client/generated/evm-accounts/evm-accounts.msw.js.map +1 -1
- package/_esm/openapi-client/generated/index.msw.js +4 -3
- package/_esm/openapi-client/generated/index.msw.js.map +1 -1
- package/_esm/openapi-client/generated/payments-alpha/payments-alpha.js +42 -0
- package/_esm/openapi-client/generated/payments-alpha/payments-alpha.js.map +1 -0
- package/_esm/openapi-client/generated/payments-alpha/payments-alpha.msw.js +250 -0
- package/_esm/openapi-client/generated/payments-alpha/payments-alpha.msw.js.map +1 -0
- package/_esm/openapi-client/index.js +3 -0
- package/_esm/openapi-client/index.js.map +1 -1
- package/_esm/version.js +1 -1
- package/_esm/version.js.map +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 +1 -2
- package/_types/accounts/evm/types.d.ts.map +1 -1
- package/_types/actions/evm/fund/Quote.d.ts +51 -0
- package/_types/actions/evm/fund/Quote.d.ts.map +1 -0
- package/_types/actions/evm/fund/fund.d.ts +25 -0
- package/_types/actions/evm/fund/fund.d.ts.map +1 -0
- package/_types/actions/evm/fund/quoteFund.d.ts +25 -0
- package/_types/actions/evm/fund/quoteFund.d.ts.map +1 -0
- package/_types/actions/evm/fund/types.d.ts +16 -0
- package/_types/actions/evm/fund/types.d.ts.map +1 -0
- package/_types/actions/evm/fund/waitForFundOperationReceipt.d.ts +68 -0
- package/_types/actions/evm/fund/waitForFundOperationReceipt.d.ts.map +1 -0
- package/_types/actions/evm/types.d.ts +65 -0
- package/_types/actions/evm/types.d.ts.map +1 -1
- package/_types/client/evm/constants.d.ts +5 -0
- package/_types/client/evm/constants.d.ts.map +1 -0
- package/_types/client/evm/evm.d.ts +44 -1
- package/_types/client/evm/evm.d.ts.map +1 -1
- package/_types/client/evm/evm.types.d.ts +15 -1
- package/_types/client/evm/evm.types.d.ts.map +1 -1
- package/_types/client/solana/solana.d.ts.map +1 -1
- package/_types/client/solana/solana.types.d.ts +2 -0
- package/_types/client/solana/solana.types.d.ts.map +1 -1
- package/_types/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.d.ts +258 -0
- package/_types/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.d.ts.map +1 -1
- package/_types/openapi-client/generated/evm-accounts/evm-accounts.d.ts +7 -1
- package/_types/openapi-client/generated/evm-accounts/evm-accounts.d.ts.map +1 -1
- package/_types/openapi-client/generated/evm-accounts/evm-accounts.msw.d.ts +2 -0
- package/_types/openapi-client/generated/evm-accounts/evm-accounts.msw.d.ts.map +1 -1
- package/_types/openapi-client/generated/index.msw.d.ts +4 -3
- package/_types/openapi-client/generated/index.msw.d.ts.map +1 -1
- package/_types/openapi-client/generated/payments-alpha/payments-alpha.d.ts +42 -0
- package/_types/openapi-client/generated/payments-alpha/payments-alpha.d.ts.map +1 -0
- package/_types/openapi-client/generated/payments-alpha/payments-alpha.msw.d.ts +20 -0
- package/_types/openapi-client/generated/payments-alpha/payments-alpha.msw.d.ts.map +1 -0
- package/_types/openapi-client/index.d.ts +8 -0
- package/_types/openapi-client/index.d.ts.map +1 -1
- package/_types/types/misc.d.ts +2 -2
- package/_types/types/misc.d.ts.map +1 -1
- package/_types/version.d.ts +1 -1
- package/_types/version.d.ts.map +1 -1
- package/accounts/evm/toEvmServerAccount.ts +26 -0
- package/accounts/evm/toEvmSmartAccount.ts +26 -0
- package/accounts/evm/types.ts +1 -2
- package/actions/evm/fund/Quote.ts +83 -0
- package/actions/evm/fund/fund.ts +76 -0
- package/actions/evm/fund/quoteFund.ts +81 -0
- package/actions/evm/fund/types.ts +16 -0
- package/actions/evm/fund/waitForFundOperationReceipt.ts +118 -0
- package/actions/evm/types.ts +73 -0
- package/client/evm/constants.ts +17 -0
- package/client/evm/evm.ts +91 -0
- package/client/evm/evm.types.ts +16 -0
- package/client/solana/solana.ts +4 -1
- package/client/solana/solana.types.ts +2 -0
- package/openapi-client/generated/coinbaseDeveloperPlatformAPIs.schemas.ts +300 -0
- package/openapi-client/generated/evm-accounts/evm-accounts.msw.ts +41 -0
- package/openapi-client/generated/evm-accounts/evm-accounts.ts +20 -0
- package/openapi-client/generated/index.msw.ts +4 -3
- package/openapi-client/generated/payments-alpha/payments-alpha.msw.ts +369 -0
- package/openapi-client/generated/payments-alpha/payments-alpha.ts +96 -0
- package/openapi-client/index.ts +3 -0
- package/package.json +1 -1
- package/types/misc.ts +2 -2
- package/version.ts +1 -1
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { type TransactionSerializable, serializeTransaction } from "viem";
|
|
2
2
|
|
|
3
|
+
import { FundOptions, fund } from "../../actions/evm/fund/fund.js";
|
|
4
|
+
import { Quote } from "../../actions/evm/fund/Quote.js";
|
|
5
|
+
import { QuoteFundOptions, quoteFund } from "../../actions/evm/fund/quoteFund.js";
|
|
6
|
+
import { FundOperationResult } from "../../actions/evm/fund/types.js";
|
|
7
|
+
import {
|
|
8
|
+
WaitForFundOperationOptions,
|
|
9
|
+
WaitForFundOperationResult,
|
|
10
|
+
waitForFundOperationReceipt,
|
|
11
|
+
} from "../../actions/evm/fund/waitForFundOperationReceipt.js";
|
|
3
12
|
import {
|
|
4
13
|
listTokenBalances,
|
|
5
14
|
type ListTokenBalancesResult,
|
|
@@ -95,6 +104,23 @@ export function toEvmServerAccount(
|
|
|
95
104
|
address: this.address,
|
|
96
105
|
});
|
|
97
106
|
},
|
|
107
|
+
async quoteFund(options: Omit<QuoteFundOptions, "address">): Promise<Quote> {
|
|
108
|
+
return quoteFund(apiClient, {
|
|
109
|
+
...options,
|
|
110
|
+
address: this.address,
|
|
111
|
+
});
|
|
112
|
+
},
|
|
113
|
+
async fund(options: Omit<FundOptions, "address">): Promise<FundOperationResult> {
|
|
114
|
+
return fund(apiClient, {
|
|
115
|
+
...options,
|
|
116
|
+
address: this.address,
|
|
117
|
+
});
|
|
118
|
+
},
|
|
119
|
+
async waitForFundOperationReceipt(
|
|
120
|
+
options: WaitForFundOperationOptions,
|
|
121
|
+
): Promise<WaitForFundOperationResult> {
|
|
122
|
+
return waitForFundOperationReceipt(apiClient, options);
|
|
123
|
+
},
|
|
98
124
|
name: options.account.name,
|
|
99
125
|
type: "evm-server",
|
|
100
126
|
policies: options.account.policies,
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import { fund, FundOptions } from "../../actions/evm/fund/fund.js";
|
|
2
|
+
import { Quote } from "../../actions/evm/fund/Quote.js";
|
|
3
|
+
import { quoteFund, QuoteFundOptions } from "../../actions/evm/fund/quoteFund.js";
|
|
4
|
+
import { FundOperationResult } from "../../actions/evm/fund/types.js";
|
|
5
|
+
import {
|
|
6
|
+
WaitForFundOperationResult,
|
|
7
|
+
waitForFundOperationReceipt,
|
|
8
|
+
WaitForFundOperationOptions,
|
|
9
|
+
} from "../../actions/evm/fund/waitForFundOperationReceipt.js";
|
|
1
10
|
import { getUserOperation } from "../../actions/evm/getUserOperation.js";
|
|
2
11
|
import {
|
|
3
12
|
listTokenBalances,
|
|
@@ -102,6 +111,23 @@ export function toEvmSmartAccount(
|
|
|
102
111
|
address: account.address,
|
|
103
112
|
});
|
|
104
113
|
},
|
|
114
|
+
async quoteFund(options: Omit<QuoteFundOptions, "address">): Promise<Quote> {
|
|
115
|
+
return quoteFund(apiClient, {
|
|
116
|
+
...options,
|
|
117
|
+
address: this.address,
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
async fund(options: Omit<FundOptions, "address">): Promise<FundOperationResult> {
|
|
121
|
+
return fund(apiClient, {
|
|
122
|
+
...options,
|
|
123
|
+
address: this.address,
|
|
124
|
+
});
|
|
125
|
+
},
|
|
126
|
+
async waitForFundOperationReceipt(
|
|
127
|
+
options: WaitForFundOperationOptions,
|
|
128
|
+
): Promise<WaitForFundOperationResult> {
|
|
129
|
+
return waitForFundOperationReceipt(apiClient, options);
|
|
130
|
+
},
|
|
105
131
|
name: options.smartAccount.name,
|
|
106
132
|
type: "evm-smart",
|
|
107
133
|
};
|
package/accounts/evm/types.ts
CHANGED
|
@@ -3,8 +3,7 @@ import { SignableMessage, TransactionSerializable } from "viem";
|
|
|
3
3
|
import { Prettify } from "../../types/utils.js";
|
|
4
4
|
|
|
5
5
|
import type { AccountActions, SmartAccountActions } from "../../actions/evm/types.js";
|
|
6
|
-
import type { EIP712Message } from "../../
|
|
7
|
-
import type { Address, Hash, Hex } from "../../types/misc.js";
|
|
6
|
+
import type { Address, EIP712Message, Hash, Hex } from "../../types/misc.js";
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* Base type for any Ethereum account with signing capabilities.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { FundOperationResult } from "./types.js";
|
|
2
|
+
import { CdpOpenApiClientType } from "../../../openapi-client/index.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A class representing a funding quote that can be executed.
|
|
6
|
+
*/
|
|
7
|
+
export class Quote {
|
|
8
|
+
/** Quote for the transfer. */
|
|
9
|
+
public quoteId: string;
|
|
10
|
+
/** Network to transfer the funds to. */
|
|
11
|
+
public network: "base" | "ethereum";
|
|
12
|
+
/** The amount in fiat currency. */
|
|
13
|
+
public fiatAmount: string;
|
|
14
|
+
/** The fiat currency. */
|
|
15
|
+
public fiatCurrency: string;
|
|
16
|
+
/** The amount in the token to transfer. */
|
|
17
|
+
public tokenAmount: string;
|
|
18
|
+
/** The token to transfer. */
|
|
19
|
+
public token: string;
|
|
20
|
+
/** Fees in the token to transfer. */
|
|
21
|
+
public fees: {
|
|
22
|
+
/** The type of fee. */
|
|
23
|
+
type: "exchange_fee" | "network_fee";
|
|
24
|
+
amount: string;
|
|
25
|
+
currency: string;
|
|
26
|
+
}[];
|
|
27
|
+
|
|
28
|
+
private apiClient: CdpOpenApiClientType;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new Quote instance.
|
|
32
|
+
*
|
|
33
|
+
* @param apiClient - The API client.
|
|
34
|
+
* @param quoteId - The quote ID.
|
|
35
|
+
* @param network - The network to transfer funds to.
|
|
36
|
+
* @param fiatAmount - The amount in fiat currency.
|
|
37
|
+
* @param fiatCurrency - The fiat currency.
|
|
38
|
+
* @param tokenAmount - The amount in the token to transfer.
|
|
39
|
+
* @param token - The token to transfer.
|
|
40
|
+
* @param fees - Fees for the transfer.
|
|
41
|
+
*/
|
|
42
|
+
constructor(
|
|
43
|
+
apiClient: CdpOpenApiClientType,
|
|
44
|
+
quoteId: string,
|
|
45
|
+
network: "base" | "ethereum",
|
|
46
|
+
fiatAmount: string,
|
|
47
|
+
fiatCurrency: string,
|
|
48
|
+
tokenAmount: string,
|
|
49
|
+
token: string,
|
|
50
|
+
fees: {
|
|
51
|
+
type: "exchange_fee" | "network_fee";
|
|
52
|
+
amount: string;
|
|
53
|
+
currency: string;
|
|
54
|
+
}[],
|
|
55
|
+
) {
|
|
56
|
+
this.apiClient = apiClient;
|
|
57
|
+
this.quoteId = quoteId;
|
|
58
|
+
this.network = network;
|
|
59
|
+
this.fiatAmount = fiatAmount;
|
|
60
|
+
this.fiatCurrency = fiatCurrency;
|
|
61
|
+
this.tokenAmount = tokenAmount;
|
|
62
|
+
this.token = token;
|
|
63
|
+
this.fees = fees;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Executes the quote to perform the actual fund transfer.
|
|
68
|
+
*
|
|
69
|
+
* @returns A promise that resolves to the result of the executed quote.
|
|
70
|
+
*/
|
|
71
|
+
async execute(): Promise<FundOperationResult> {
|
|
72
|
+
const transfer = await this.apiClient.executePaymentTransferQuote(this.quoteId);
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
id: transfer.id,
|
|
76
|
+
network: transfer.target.network,
|
|
77
|
+
targetAmount: transfer.targetAmount,
|
|
78
|
+
targetCurrency: transfer.targetCurrency,
|
|
79
|
+
status: transfer.status,
|
|
80
|
+
transactionHash: transfer.transactionHash,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { formatUnits } from "viem";
|
|
2
|
+
|
|
3
|
+
import { FundOperationResult } from "./types.js";
|
|
4
|
+
import {
|
|
5
|
+
CreatePaymentTransferQuoteBodySourceType,
|
|
6
|
+
CreatePaymentTransferQuoteBodyTargetType,
|
|
7
|
+
type CdpOpenApiClientType,
|
|
8
|
+
} from "../../../openapi-client/index.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Options for funding an EVM account.
|
|
12
|
+
*/
|
|
13
|
+
export interface FundOptions {
|
|
14
|
+
/** The address of the account. */
|
|
15
|
+
address: string;
|
|
16
|
+
/** The network to request funds from. */
|
|
17
|
+
network: "base";
|
|
18
|
+
/** The amount to fund the account with, in atomic units (wei) of the token. */
|
|
19
|
+
amount: bigint;
|
|
20
|
+
/** The token to request funds for. */
|
|
21
|
+
token: "eth" | "usdc";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Funds an EVM account.
|
|
26
|
+
*
|
|
27
|
+
* @param apiClient - The API client.
|
|
28
|
+
* @param options - The options for funding an EVM account.
|
|
29
|
+
*
|
|
30
|
+
* @returns A promise that resolves to the fund operation result.
|
|
31
|
+
*/
|
|
32
|
+
export async function fund(
|
|
33
|
+
apiClient: CdpOpenApiClientType,
|
|
34
|
+
options: FundOptions,
|
|
35
|
+
): Promise<FundOperationResult> {
|
|
36
|
+
const paymentMethods = await apiClient.getPaymentMethods();
|
|
37
|
+
const cardPaymentMethod = paymentMethods.find(
|
|
38
|
+
method => method.type === "card" && method.actions.includes("source"),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
if (!cardPaymentMethod) {
|
|
42
|
+
throw new Error("No card found to fund account");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (options.token.toLowerCase() !== "eth" && options.token.toLowerCase() !== "usdc") {
|
|
46
|
+
throw new Error("Invalid currency, must be eth or usdc");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const decimals = options.token === "eth" ? 18 : 6;
|
|
50
|
+
const amount = formatUnits(options.amount, decimals);
|
|
51
|
+
|
|
52
|
+
const response = await apiClient.createPaymentTransferQuote({
|
|
53
|
+
sourceType: CreatePaymentTransferQuoteBodySourceType.payment_method,
|
|
54
|
+
source: {
|
|
55
|
+
id: cardPaymentMethod.id,
|
|
56
|
+
},
|
|
57
|
+
targetType: CreatePaymentTransferQuoteBodyTargetType.crypto_rail,
|
|
58
|
+
target: {
|
|
59
|
+
currency: options.token,
|
|
60
|
+
network: options.network,
|
|
61
|
+
address: options.address,
|
|
62
|
+
},
|
|
63
|
+
amount,
|
|
64
|
+
currency: options.token,
|
|
65
|
+
execute: true,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
id: response.transfer.id,
|
|
70
|
+
network: response.transfer.target.network,
|
|
71
|
+
status: response.transfer.status,
|
|
72
|
+
targetAmount: response.transfer.targetAmount,
|
|
73
|
+
targetCurrency: response.transfer.targetCurrency,
|
|
74
|
+
transactionHash: response.transfer.transactionHash,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { formatUnits } from "viem";
|
|
2
|
+
|
|
3
|
+
import { Quote } from "./Quote.js";
|
|
4
|
+
import {
|
|
5
|
+
CreatePaymentTransferQuoteBodySourceType,
|
|
6
|
+
CreatePaymentTransferQuoteBodyTargetType,
|
|
7
|
+
type CdpOpenApiClientType,
|
|
8
|
+
} from "../../../openapi-client/index.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Options for getting a quote to fund an EVM account.
|
|
12
|
+
*/
|
|
13
|
+
export interface QuoteFundOptions {
|
|
14
|
+
/** The address of the account. */
|
|
15
|
+
address: string;
|
|
16
|
+
/** The network to request funds from. */
|
|
17
|
+
network: "base";
|
|
18
|
+
/** The amount to fund the account with, in atomic units (wei) of the token. */
|
|
19
|
+
amount: bigint;
|
|
20
|
+
/** The token to request funds for. */
|
|
21
|
+
token: "eth" | "usdc";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Gets a quote to fund an EVM account.
|
|
26
|
+
*
|
|
27
|
+
* @param apiClient - The API client.
|
|
28
|
+
* @param options - The options for getting a quote to fund an EVM account.
|
|
29
|
+
*
|
|
30
|
+
* @returns A promise that resolves to the quote.
|
|
31
|
+
*/
|
|
32
|
+
export async function quoteFund(
|
|
33
|
+
apiClient: CdpOpenApiClientType,
|
|
34
|
+
options: QuoteFundOptions,
|
|
35
|
+
): Promise<Quote> {
|
|
36
|
+
const paymentMethods = await apiClient.getPaymentMethods();
|
|
37
|
+
const cardPaymentMethod = paymentMethods.find(
|
|
38
|
+
method => method.type === "card" && method.actions.includes("source"),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
if (!cardPaymentMethod) {
|
|
42
|
+
throw new Error("No card found to fund account");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (options.token.toLowerCase() !== "eth" && options.token.toLowerCase() !== "usdc") {
|
|
46
|
+
throw new Error("Invalid currency, must be eth or usdc");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const decimals = options.token === "eth" ? 18 : 6;
|
|
50
|
+
const amount = formatUnits(options.amount, decimals);
|
|
51
|
+
|
|
52
|
+
const response = await apiClient.createPaymentTransferQuote({
|
|
53
|
+
sourceType: CreatePaymentTransferQuoteBodySourceType.payment_method,
|
|
54
|
+
source: {
|
|
55
|
+
id: cardPaymentMethod.id,
|
|
56
|
+
},
|
|
57
|
+
targetType: CreatePaymentTransferQuoteBodyTargetType.crypto_rail,
|
|
58
|
+
target: {
|
|
59
|
+
currency: options.token,
|
|
60
|
+
network: options.network,
|
|
61
|
+
address: options.address,
|
|
62
|
+
},
|
|
63
|
+
amount,
|
|
64
|
+
currency: options.token,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return new Quote(
|
|
68
|
+
apiClient,
|
|
69
|
+
response.transfer.id,
|
|
70
|
+
options.network,
|
|
71
|
+
response.transfer.sourceAmount,
|
|
72
|
+
response.transfer.sourceCurrency,
|
|
73
|
+
response.transfer.targetAmount,
|
|
74
|
+
response.transfer.targetCurrency,
|
|
75
|
+
response.transfer.fees.map(fee => ({
|
|
76
|
+
type: fee.type,
|
|
77
|
+
amount: fee.amount,
|
|
78
|
+
currency: fee.currency,
|
|
79
|
+
})),
|
|
80
|
+
);
|
|
81
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TransferStatus } from "../../../openapi-client/index.js";
|
|
2
|
+
|
|
3
|
+
export type FundOperationResult = {
|
|
4
|
+
/** The transfer that was created to fund the account. */
|
|
5
|
+
id: string;
|
|
6
|
+
/** The network that the transfer was created on. */
|
|
7
|
+
network: string;
|
|
8
|
+
/** The target amount that will be received. */
|
|
9
|
+
targetAmount: string;
|
|
10
|
+
/** The currency that will be received. */
|
|
11
|
+
targetCurrency: string;
|
|
12
|
+
/** The status of the fund operation. */
|
|
13
|
+
status: TransferStatus;
|
|
14
|
+
/** The transaction hash of the transfer. */
|
|
15
|
+
transactionHash?: string;
|
|
16
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { CdpOpenApiClientType, Transfer, TransferStatus } from "../../../openapi-client/index.js";
|
|
2
|
+
import { wait, WaitOptions } from "../../../utils/wait.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Options for waiting for a fund operation.
|
|
6
|
+
*/
|
|
7
|
+
export type WaitForFundOperationOptions = {
|
|
8
|
+
/** The ID of the transfer to wait for. */
|
|
9
|
+
transferId: string;
|
|
10
|
+
/** Optional options for the wait operation. */
|
|
11
|
+
waitOptions?: WaitOptions;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Represents a failed fund operation.
|
|
16
|
+
*/
|
|
17
|
+
export type FailedFundOperation = {
|
|
18
|
+
/** The ID of the transfer. */
|
|
19
|
+
id: string;
|
|
20
|
+
/** The network that the transfer was created on. */
|
|
21
|
+
network: string;
|
|
22
|
+
/** The target amount that will be received. */
|
|
23
|
+
targetAmount: string;
|
|
24
|
+
/** The currency that will be received. */
|
|
25
|
+
targetCurrency: string;
|
|
26
|
+
/** The status of the transfer. */
|
|
27
|
+
status: typeof TransferStatus.failed;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Represents a completed fund operation.
|
|
32
|
+
*/
|
|
33
|
+
export type CompletedFundOperation = {
|
|
34
|
+
/** The ID of the transfer. */
|
|
35
|
+
id: string;
|
|
36
|
+
/** The network that the transfer was created on. */
|
|
37
|
+
network: string;
|
|
38
|
+
/** The target amount that will be received. */
|
|
39
|
+
targetAmount: string;
|
|
40
|
+
/** The currency that will be received. */
|
|
41
|
+
targetCurrency: string;
|
|
42
|
+
/** The status of the transfer. */
|
|
43
|
+
status: typeof TransferStatus.completed;
|
|
44
|
+
/** The transaction hash of the transfer. */
|
|
45
|
+
transactionHash: string;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Represents the return type of the waitForFundOperation function.
|
|
50
|
+
*/
|
|
51
|
+
export type WaitForFundOperationResult = FailedFundOperation | CompletedFundOperation;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Waits for a fund operation to complete or fail.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* import { waitForFundOperation } from "@coinbase/cdp-sdk";
|
|
59
|
+
*
|
|
60
|
+
* const result = await waitForFundOperation(client, {
|
|
61
|
+
* transferId: "0x1234567890123456789012345678901234567890",
|
|
62
|
+
* waitOptions: {
|
|
63
|
+
* timeoutSeconds: 30,
|
|
64
|
+
* },
|
|
65
|
+
* });
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @param {CdpOpenApiClientType} client - The client to use to wait for the fund operation.
|
|
69
|
+
* @param {WaitForFundOperationOptions} options - The options for the wait operation.
|
|
70
|
+
* @returns {Promise<WaitForFundOperationResult>} The result of the fund operation.
|
|
71
|
+
*/
|
|
72
|
+
export async function waitForFundOperationReceipt(
|
|
73
|
+
client: CdpOpenApiClientType,
|
|
74
|
+
options: WaitForFundOperationOptions,
|
|
75
|
+
): Promise<WaitForFundOperationResult> {
|
|
76
|
+
const { transferId } = options;
|
|
77
|
+
|
|
78
|
+
const reload = async () => {
|
|
79
|
+
const response = await client.getPaymentTransfer(transferId);
|
|
80
|
+
return response;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const transform = (operation: Transfer): WaitForFundOperationResult => {
|
|
84
|
+
if (operation.status === TransferStatus.failed) {
|
|
85
|
+
return {
|
|
86
|
+
id: operation.id,
|
|
87
|
+
network: operation.target.network,
|
|
88
|
+
targetAmount: operation.targetAmount,
|
|
89
|
+
targetCurrency: operation.targetCurrency,
|
|
90
|
+
status: operation.status,
|
|
91
|
+
} satisfies FailedFundOperation;
|
|
92
|
+
} else if (operation.status === TransferStatus.completed) {
|
|
93
|
+
return {
|
|
94
|
+
id: operation.id,
|
|
95
|
+
network: operation.target.network,
|
|
96
|
+
targetAmount: operation.targetAmount,
|
|
97
|
+
targetCurrency: operation.targetCurrency,
|
|
98
|
+
status: operation.status,
|
|
99
|
+
transactionHash: operation.transactionHash!,
|
|
100
|
+
} satisfies CompletedFundOperation;
|
|
101
|
+
} else {
|
|
102
|
+
throw new Error("Transfer is not terminal");
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const waitOptions = options.waitOptions || {
|
|
107
|
+
timeoutSeconds: 900,
|
|
108
|
+
intervalSeconds: 1,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
return await wait(reload, isTerminal, transform, waitOptions);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const isTerminal = (operation: Transfer): boolean => {
|
|
115
|
+
return (
|
|
116
|
+
operation.status === TransferStatus.completed || operation.status === TransferStatus.failed
|
|
117
|
+
);
|
|
118
|
+
};
|
package/actions/evm/types.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import { FundOptions } from "./fund/fund.js";
|
|
2
|
+
import { Quote } from "./fund/Quote.js";
|
|
3
|
+
import { QuoteFundOptions } from "./fund/quoteFund.js";
|
|
4
|
+
import { FundOperationResult } from "./fund/types.js";
|
|
5
|
+
import {
|
|
6
|
+
WaitForFundOperationOptions,
|
|
7
|
+
WaitForFundOperationResult,
|
|
8
|
+
} from "./fund/waitForFundOperationReceipt.js";
|
|
1
9
|
import { SendUserOperationOptions, SendUserOperationReturnType } from "./sendUserOperation.js";
|
|
2
10
|
import { GetUserOperationOptions, UserOperation } from "../../client/evm/evm.types.js";
|
|
3
11
|
import { Hex } from "../../types/misc.js";
|
|
@@ -50,6 +58,71 @@ type Actions = {
|
|
|
50
58
|
* ```
|
|
51
59
|
*/
|
|
52
60
|
requestFaucet: (options: Omit<RequestFaucetOptions, "address">) => Promise<RequestFaucetResult>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Gets a quote to fund an EVM account.
|
|
64
|
+
*
|
|
65
|
+
* @param options - The options for the quote fund.
|
|
66
|
+
* @param options.network - The network to fund the account on.
|
|
67
|
+
* @param options.token - The token to fund the account with.
|
|
68
|
+
* @param options.amount - The amount of the token to fund represented as an atomic unit.
|
|
69
|
+
* It's common to use `parseUnits` utils from viem to convert to atomic units.
|
|
70
|
+
* Otherwise, you can pass atomic units directly.
|
|
71
|
+
*
|
|
72
|
+
* @returns A promise that resolves to a Quote object containing details about the funding operation.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* const quote = await account.quoteFund({
|
|
77
|
+
* network: "base",
|
|
78
|
+
* token: "usdc",
|
|
79
|
+
* amount: 1000000n,
|
|
80
|
+
* });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
quoteFund: (options: Omit<QuoteFundOptions, "address">) => Promise<Quote>;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Funds an EVM account with the specified token amount.
|
|
87
|
+
*
|
|
88
|
+
* @param options - The options for the fund operation.
|
|
89
|
+
* @param options.network - The network to fund the account on.
|
|
90
|
+
* @param options.token - The token to fund the account with (e.g., 'usdc').
|
|
91
|
+
* @param options.amount - The amount of the token to fund represented as an atomic unit.
|
|
92
|
+
* It's common to use `parseUnits` utils from viem to convert to atomic units.
|
|
93
|
+
* Otherwise, you can pass atomic units directly.
|
|
94
|
+
*
|
|
95
|
+
* @returns A promise that resolves to the fund operation result containing the transfer details.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* const fundOperation = await account.fund({
|
|
100
|
+
* network: "base",
|
|
101
|
+
* token: "usdc",
|
|
102
|
+
* amount: 1000000n,
|
|
103
|
+
* });
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
fund: (options: Omit<FundOptions, "address">) => Promise<FundOperationResult>;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Waits for a fund operation to complete and returns the transfer receipt.
|
|
110
|
+
*
|
|
111
|
+
* @param options - The options for the wait for fund operation.
|
|
112
|
+
* @param options.transferId - The ID of the transfer to wait for.
|
|
113
|
+
*
|
|
114
|
+
* @returns A promise that resolves to the completed transfer receipt containing details about the funding operation.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```ts
|
|
118
|
+
* const completedTransfer = await account.waitForFundOperationReceipt({
|
|
119
|
+
* transferId: "transfer_123",
|
|
120
|
+
* });
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
waitForFundOperationReceipt(
|
|
124
|
+
options: WaitForFundOperationOptions,
|
|
125
|
+
): Promise<WaitForFundOperationResult>;
|
|
53
126
|
};
|
|
54
127
|
|
|
55
128
|
export type AccountActions = Actions & {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The public RSA key used to encrypt the private key when importing an EVM account.
|
|
3
|
+
*/
|
|
4
|
+
export const ImportEvmAccountPublicRSAKey = `-----BEGIN PUBLIC KEY-----
|
|
5
|
+
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2Fxydgm/ryYk0IexQIuL
|
|
6
|
+
9DKyiIk2WmS36AZ83a9Z0QX53qdveg08b05g1Qr+o+COoYOT/FDi8anRGAs7rIyS
|
|
7
|
+
uigrjHR6VrmFjnGrrTr3MINwC9cYQFHwET8YVGRq+BB3iFTB1kIb9XJ/vT2sk1xP
|
|
8
|
+
hJ6JihEwSl4DgbeVjqw59wYqrNg355oa8EdFqkmfGU2tpbM56F8iv1F+shwkGo3y
|
|
9
|
+
GhW/UOQ5OLauXvsqo8ranwsK+lqFblLEMlNtn1VSJeO2vMxryeKFrY2ob8VqGchC
|
|
10
|
+
ftPJiLWs2Du6juw4C1rOWwSMlXzZ6cNMHkxdTcEHMr3C2TEHgzjZY41whMwNTB8q
|
|
11
|
+
/pxXnIbH77caaviRs4R/POe8cSsznalXj85LULvFWOIHp0w+jEYSii9Rp9XtHWAH
|
|
12
|
+
nrK/O/SVDtT1ohp2F+Zg1mojTgKfLOyGdOUXTi95naDTuG770rSjHdL80tJBz1Fd
|
|
13
|
+
+1pzGTGXGHLZQLX5YZm5iuy2cebWfF09VjIoCIlDB2++tr4M+O0Z1X1ZE0J5Ackq
|
|
14
|
+
rOluAFalaKynyH3KMyRg+NuLmibu5OmcMjCLK3D4X1YLiN2OK8/bbpEL8JYroDwb
|
|
15
|
+
EXIUW5mGS06YxfSUsxHzL9Tj00+GMm/Gvl0+4/+Vn8IXVHjQOSPNEy3EnqCiH/OW
|
|
16
|
+
8v0IMC32CeGrX7mGbU+MzlsCAwEAAQ==
|
|
17
|
+
-----END PUBLIC KEY-----`;
|
package/client/evm/evm.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { publicEncrypt, constants } from "crypto";
|
|
2
|
+
|
|
1
3
|
import { Address } from "viem";
|
|
2
4
|
|
|
5
|
+
import { ImportEvmAccountPublicRSAKey } from "./constants.js";
|
|
3
6
|
import {
|
|
4
7
|
CreateServerAccountOptions,
|
|
5
8
|
GetServerAccountOptions,
|
|
@@ -23,6 +26,7 @@ import {
|
|
|
23
26
|
GetOrCreateServerAccountOptions,
|
|
24
27
|
SignTypedDataOptions,
|
|
25
28
|
UpdateEvmAccountOptions,
|
|
29
|
+
ImportServerAccountOptions,
|
|
26
30
|
} from "./evm.types.js";
|
|
27
31
|
import { toEvmServerAccount } from "../../accounts/evm/toEvmServerAccount.js";
|
|
28
32
|
import { toEvmSmartAccount } from "../../accounts/evm/toEvmSmartAccount.js";
|
|
@@ -99,6 +103,7 @@ export class EvmClient implements EvmClientInterface {
|
|
|
99
103
|
const openApiAccount = await CdpOpenApiClient.createEvmAccount(
|
|
100
104
|
{
|
|
101
105
|
name: options.name,
|
|
106
|
+
accountPolicy: options.accountPolicy,
|
|
102
107
|
},
|
|
103
108
|
options.idempotencyKey,
|
|
104
109
|
);
|
|
@@ -112,6 +117,92 @@ export class EvmClient implements EvmClientInterface {
|
|
|
112
117
|
return account;
|
|
113
118
|
}
|
|
114
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Imports a CDP EVM account from an external source.
|
|
122
|
+
*
|
|
123
|
+
* @param {ImportServerAccountOptions} options - Parameters for importing the account.
|
|
124
|
+
* @param {string} options.privateKey - The private key of the account to import.
|
|
125
|
+
* @param {string} [options.name] - A name for the account to import.
|
|
126
|
+
* @param {string} [options.idempotencyKey] - An idempotency key.
|
|
127
|
+
*
|
|
128
|
+
* @returns A promise that resolves to the imported account.
|
|
129
|
+
*
|
|
130
|
+
* @example **Without arguments**
|
|
131
|
+
* ```ts
|
|
132
|
+
* const account = await cdp.evm.importAccount({
|
|
133
|
+
* privateKey: "0x123456"
|
|
134
|
+
* });
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @example **With a name**
|
|
138
|
+
* ```ts
|
|
139
|
+
* const account = await cdp.evm.importAccount({
|
|
140
|
+
* privateKey: "0x123456",
|
|
141
|
+
* name: "MyAccount"
|
|
142
|
+
* });
|
|
143
|
+
* ```
|
|
144
|
+
*
|
|
145
|
+
* @example **With an idempotency key**
|
|
146
|
+
* ```ts
|
|
147
|
+
* const idempotencyKey = uuidv4();
|
|
148
|
+
*
|
|
149
|
+
* // First call
|
|
150
|
+
* await cdp.evm.importAccount({
|
|
151
|
+
* privateKey: "0x123456",
|
|
152
|
+
* idempotencyKey,
|
|
153
|
+
* });
|
|
154
|
+
*
|
|
155
|
+
* // Second call with the same idempotency key will return the same account
|
|
156
|
+
* await cdp.evm.importAccount({
|
|
157
|
+
* privateKey: "0x123456"
|
|
158
|
+
* idempotencyKey,
|
|
159
|
+
* });
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
async importAccount(options: ImportServerAccountOptions): Promise<ServerAccount> {
|
|
163
|
+
const privateKeyHex = options.privateKey.startsWith("0x")
|
|
164
|
+
? options.privateKey.slice(2)
|
|
165
|
+
: options.privateKey;
|
|
166
|
+
|
|
167
|
+
if (!/^[0-9a-fA-F]+$/.test(privateKeyHex)) {
|
|
168
|
+
throw new Error("Private key must be a valid hexadecimal string");
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
const privateKeyBytes = Buffer.from(privateKeyHex, "hex");
|
|
173
|
+
|
|
174
|
+
const encryptedPrivateKey = publicEncrypt(
|
|
175
|
+
{
|
|
176
|
+
key: ImportEvmAccountPublicRSAKey,
|
|
177
|
+
padding: constants.RSA_PKCS1_OAEP_PADDING,
|
|
178
|
+
oaepHash: "sha256",
|
|
179
|
+
},
|
|
180
|
+
privateKeyBytes,
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
const openApiAccount = await CdpOpenApiClient.importEvmAccount(
|
|
184
|
+
{
|
|
185
|
+
name: options.name,
|
|
186
|
+
encryptedPrivateKey: encryptedPrivateKey.toString("base64"),
|
|
187
|
+
},
|
|
188
|
+
options.idempotencyKey,
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const account = toEvmServerAccount(CdpOpenApiClient, {
|
|
192
|
+
account: openApiAccount,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
Analytics.wrapObjectMethodsWithErrorTracking(account);
|
|
196
|
+
|
|
197
|
+
return account;
|
|
198
|
+
} catch (error) {
|
|
199
|
+
if (error instanceof APIError) {
|
|
200
|
+
throw error;
|
|
201
|
+
}
|
|
202
|
+
throw new Error(`Failed to import account: ${String(error)}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
115
206
|
/**
|
|
116
207
|
* Creates a new CDP EVM smart account.
|
|
117
208
|
*
|