@coinbase/agentkit
Version:
Coinbase AgentKit core primitives
315 lines (314 loc) • 12.5 kB
JavaScript
"use strict";
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _CdpSmartWalletProvider_publicClient, _CdpSmartWalletProvider_cdp, _CdpSmartWalletProvider_network, _CdpSmartWalletProvider_paymasterUrl;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CdpSmartWalletProvider = void 0;
const cdp_sdk_1 = require("@coinbase/cdp-sdk");
const viem_1 = require("viem");
const network_1 = require("../network");
const evmWalletProvider_1 = require("./evmWalletProvider");
/**
* A wallet provider that uses the Coinbase CDP SDK smart wallets.
*/
class CdpSmartWalletProvider extends evmWalletProvider_1.EvmWalletProvider {
/**
* Constructs a new CdpSmartWalletProvider.
*
* @param config - The configuration options for the CdpSmartWalletProvider.
*/
constructor(config) {
super();
_CdpSmartWalletProvider_publicClient.set(this, void 0);
_CdpSmartWalletProvider_cdp.set(this, void 0);
_CdpSmartWalletProvider_network.set(this, void 0);
_CdpSmartWalletProvider_paymasterUrl.set(this, void 0);
this.smartAccount = config.smartAccount;
this.ownerAccount = config.ownerAccount;
__classPrivateFieldSet(this, _CdpSmartWalletProvider_cdp, config.cdp, "f");
__classPrivateFieldSet(this, _CdpSmartWalletProvider_publicClient, config.publicClient, "f");
__classPrivateFieldSet(this, _CdpSmartWalletProvider_network, config.network, "f");
__classPrivateFieldSet(this, _CdpSmartWalletProvider_paymasterUrl, config.paymasterUrl, "f");
}
/**
* Configures a new CdpSmartWalletProvider with a smart wallet.
*
* @param config - Optional configuration parameters
* @returns A Promise that resolves to a new CdpSmartWalletProvider instance
* @throws Error if required environment variables are missing or wallet initialization fails
*/
static async configureWithWallet(config = {}) {
const apiKeyId = config.apiKeyId || process.env.CDP_API_KEY_ID;
const apiKeySecret = config.apiKeySecret || process.env.CDP_API_KEY_SECRET;
const walletSecret = config.walletSecret || process.env.CDP_WALLET_SECRET;
const idempotencyKey = config.idempotencyKey || process.env.IDEMPOTENCY_KEY;
const paymasterUrl = config.paymasterUrl || process.env.PAYMASTER_URL;
if (!apiKeyId || !apiKeySecret || !walletSecret) {
throw new Error("Missing required environment variables. CDP_API_KEY_ID, CDP_API_KEY_SECRET, CDP_WALLET_SECRET are required.");
}
const networkId = config.networkId || process.env.NETWORK_ID || "base-sepolia";
const network = {
protocolFamily: "evm",
chainId: network_1.NETWORK_ID_TO_CHAIN_ID[networkId],
networkId: networkId,
};
const cdpClient = new cdp_sdk_1.CdpClient({
apiKeyId,
apiKeySecret,
walletSecret,
});
// Create or get the owner account
const ownerAccount = await (() => {
if (typeof config.owner === "string") {
return cdpClient.evm.getAccount({ address: config.owner });
}
if (typeof config.owner === "object") {
return config.owner;
}
return cdpClient.evm.createAccount({ idempotencyKey });
})();
// Create or get the smart account
const smartAccount = await (config.address || config.smartAccountName
? cdpClient.evm.getSmartAccount({
address: config.address,
name: config.smartAccountName,
owner: ownerAccount,
})
: cdpClient.evm.createSmartAccount({
owner: ownerAccount,
}));
const rpcUrl = config.rpcUrl || process.env.RPC_URL;
const publicClient = (0, viem_1.createPublicClient)({
chain: network_1.NETWORK_ID_TO_VIEM_CHAIN[networkId],
transport: rpcUrl ? (0, viem_1.http)(rpcUrl) : (0, viem_1.http)(),
});
return new CdpSmartWalletProvider({
publicClient,
cdp: cdpClient,
smartAccount,
ownerAccount,
network,
paymasterUrl,
});
}
/**
* Exports the wallet.
*
* @returns The wallet's data.
*/
async exportWallet() {
return {
name: this.smartAccount.name,
address: this.smartAccount.address,
ownerAddress: this.ownerAccount.address,
};
}
/**
* Signs a raw hash using the owner account.
*
* @param _hash - The hash to sign.
* @returns The signed hash.
*/
async sign(_hash) {
if (!this.ownerAccount.sign) {
throw new Error("Owner account does not support raw hash signing");
}
return this.ownerAccount.sign({ hash: _hash });
}
/**
* Signs a message using the owner account.
*
* @param _message - The message to sign.
* @returns The signed message.
*/
async signMessage(_message) {
return this.ownerAccount.signMessage({ message: _message });
}
/**
* Signs a typed data object using the owner account.
*
* @param typedData - The typed data object to sign.
* @returns The signed typed data object.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async signTypedData(typedData) {
const { domain, types, primaryType, message } = typedData;
return await this.smartAccount.signTypedData({
domain,
types,
primaryType,
message,
network: this.getCdpSdkNetwork(),
});
}
/**
* Signs a transaction using the owner account.
*
* @param _ - The transaction to sign.
* @returns The signed transaction.
*/
async signTransaction(_) {
throw new Error("Direct transaction signing not supported for smart wallets. Use sendTransaction instead.");
}
/**
* Sends a user operation through the smart wallet.
*
* @param transaction - The transaction to send.
* @returns The user operation hash.
*/
async sendTransaction(transaction) {
const calls = [
{
to: transaction.to,
value: transaction.value ? BigInt(transaction.value.toString()) : 0n,
data: transaction.data || "0x",
},
];
const userOperation = await __classPrivateFieldGet(this, _CdpSmartWalletProvider_cdp, "f").evm.sendUserOperation({
smartAccount: this.smartAccount,
network: this.getCdpSdkNetwork(),
calls,
paymasterUrl: __classPrivateFieldGet(this, _CdpSmartWalletProvider_paymasterUrl, "f"),
});
return userOperation.userOpHash;
}
/**
* Gets the address of the smart wallet.
*
* @returns The address of the smart wallet.
*/
getAddress() {
return this.smartAccount.address;
}
/**
* Gets the network of the wallet.
*
* @returns The network of the wallet.
*/
getNetwork() {
return __classPrivateFieldGet(this, _CdpSmartWalletProvider_network, "f");
}
/**
* Gets the name of the wallet provider.
*
* @returns The name of the wallet provider.
*/
getName() {
return "cdp_smart_wallet_provider";
}
/**
* Gets the CDP client.
*
* @returns The CDP client.
*/
getClient() {
return __classPrivateFieldGet(this, _CdpSmartWalletProvider_cdp, "f");
}
/**
* Gets the paymaster URL for gasless transactions.
*
* @returns The paymaster URL if configured, undefined otherwise.
*/
getPaymasterUrl() {
return __classPrivateFieldGet(this, _CdpSmartWalletProvider_paymasterUrl, "f");
}
/**
* Gets the Viem PublicClient used for read-only operations.
*
* @returns The Viem PublicClient instance used for read-only operations.
*/
getPublicClient() {
return __classPrivateFieldGet(this, _CdpSmartWalletProvider_publicClient, "f");
}
/**
* Gets the balance of the smart wallet.
*
* @returns The balance of the wallet in wei
*/
async getBalance() {
return await __classPrivateFieldGet(this, _CdpSmartWalletProvider_publicClient, "f").getBalance({ address: this.smartAccount.address });
}
/**
* Waits for a user operation receipt.
*
* @param userOpHash - The user operation hash to wait for.
* @returns The user operation receipt.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async waitForTransactionReceipt(userOpHash) {
// For smart wallets, we need to wait for the user operation to be confirmed
const receipt = await __classPrivateFieldGet(this, _CdpSmartWalletProvider_cdp, "f").evm.waitForUserOperation({
smartAccountAddress: this.smartAccount.address,
userOpHash,
});
// Append transaction logs if available
if (receipt.status === "complete") {
const receiptTx = await __classPrivateFieldGet(this, _CdpSmartWalletProvider_publicClient, "f").waitForTransactionReceipt({
hash: receipt.transactionHash,
});
if (receiptTx.logs)
return { ...receipt, logs: receiptTx.logs };
}
return receipt;
}
/**
* Reads a contract.
*
* @param params - The parameters to read the contract.
* @returns The response from the contract.
*/
async readContract(params) {
return __classPrivateFieldGet(this, _CdpSmartWalletProvider_publicClient, "f").readContract(params);
}
/**
* Transfer the native asset of the network using smart wallet.
*
* @param to - The destination address.
* @param value - The amount to transfer in atomic units (Wei).
* @returns The user operation hash.
*/
async nativeTransfer(to, value) {
return this.sendTransaction({
to: to,
value: BigInt(value),
data: "0x",
});
}
/**
* Converts the internal network ID to the format expected by the CDP SDK.
*
* @returns The network ID in CDP SDK format
* @throws Error if the network is not supported
*/
getCdpSdkNetwork() {
switch (__classPrivateFieldGet(this, _CdpSmartWalletProvider_network, "f").networkId) {
case "base-sepolia":
return "base-sepolia";
case "base-mainnet":
return "base";
case "ethereum-mainnet":
return "ethereum";
case "ethereum-sepolia":
return "ethereum-sepolia";
case "polygon-mainnet":
return "polygon";
case "arbitrum-mainnet":
return "arbitrum";
case "optimism-mainnet":
return "optimism";
default:
throw new Error(`Unsupported network for smart wallets: ${__classPrivateFieldGet(this, _CdpSmartWalletProvider_network, "f").networkId}`);
}
}
}
exports.CdpSmartWalletProvider = CdpSmartWalletProvider;
_CdpSmartWalletProvider_publicClient = new WeakMap(), _CdpSmartWalletProvider_cdp = new WeakMap(), _CdpSmartWalletProvider_network = new WeakMap(), _CdpSmartWalletProvider_paymasterUrl = new WeakMap();