Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import { z } from "zod";
import { Network } from "../../network";
import { WalletProvider } from "../../wallet-providers";
import { WalletProviderWithClient } from "../../wallet-providers/cdpV2Shared";
import { isWalletProviderWithClient } from "../../wallet-providers/cdpV2Shared";
import { CreateAction } from "../actionDecorator";
import { ActionProvider } from "../actionProvider";
import { RequestFaucetFundsV2Schema } from "./schemas";

type CdpV2WalletProviderWithClient = WalletProvider & WalletProviderWithClient;

/**
* CdpApiActionProvider is an action provider for CDP API.
*
* This provider is used for any action that uses the CDP API, but does not require a CDP Wallet.
*/
export class CdpApiV2ActionProvider extends ActionProvider<CdpV2WalletProviderWithClient> {
export class CdpApiV2ActionProvider extends ActionProvider<WalletProvider> {
/**
* Constructor for the CdpApiActionProvider class.
*/
Expand All @@ -39,43 +37,47 @@ from another wallet and provide the user with your wallet details.`,
schema: RequestFaucetFundsV2Schema,
})
async faucet(
walletProvider: CdpV2WalletProviderWithClient,
walletProvider: WalletProvider,
args: z.infer<typeof RequestFaucetFundsV2Schema>,
): Promise<string> {
const network = walletProvider.getNetwork();
const networkId = network.networkId!;

if (network.protocolFamily === "evm") {
if (networkId !== "base-sepolia" && networkId !== "ethereum-sepolia") {
throw new Error(
"Faucet is only supported on 'base-sepolia' or 'ethereum-sepolia' evm networks.",
);
}
if (isWalletProviderWithClient(walletProvider)) {
if (network.protocolFamily === "evm") {
if (networkId !== "base-sepolia" && networkId !== "ethereum-sepolia") {
throw new Error(
"Faucet is only supported on 'base-sepolia' or 'ethereum-sepolia' evm networks.",
);
}

const faucetTx = await walletProvider.getClient().evm.requestFaucet({
address: walletProvider.getAddress(),
token: (args.assetId || "eth") as "eth" | "usdc" | "eurc" | "cbbtc",
network: networkId,
});
const faucetTx = await walletProvider.getClient().evm.requestFaucet({
address: walletProvider.getAddress(),
token: (args.assetId || "eth") as "eth" | "usdc" | "eurc" | "cbbtc",
network: networkId,
});

return `Received ${
args.assetId || "ETH"
} from the faucet. Transaction hash: ${faucetTx.transactionHash}`;
} else if (network.protocolFamily === "svm") {
if (networkId !== "solana-devnet") {
throw new Error("Faucet is only supported on 'solana-devnet' solana networks.");
}
return `Received ${
args.assetId || "ETH"
} from the faucet. Transaction hash: ${faucetTx.transactionHash}`;
} else if (network.protocolFamily === "svm") {
if (networkId !== "solana-devnet") {
throw new Error("Faucet is only supported on 'solana-devnet' solana networks.");
}

const faucetTx = await walletProvider.getClient().solana.requestFaucet({
address: walletProvider.getAddress(),
token: (args.assetId || "sol") as "sol" | "usdc",
});
const faucetTx = await walletProvider.getClient().solana.requestFaucet({
address: walletProvider.getAddress(),
token: (args.assetId || "sol") as "sol" | "usdc",
});

return `Received ${
args.assetId || "SOL"
} from the faucet. Transaction signature hash: ${faucetTx.signature}`;
return `Received ${
args.assetId || "SOL"
} from the faucet. Transaction signature hash: ${faucetTx.signature}`;
} else {
throw new Error("Faucet is only supported on Ethereum and Solana protocol families.");
}
} else {
throw new Error("Faucet is only supported on Ethereum and Solana protocol families.");
throw new Error("Wallet provider is not a CDP Wallet Provider.");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,30 @@ export class CdpV2EvmWalletProvider extends EvmWalletProvider implements WalletP
* @returns The hash of the transaction.
*/
async sendTransaction(transaction: TransactionRequest): Promise<Hex> {
const txWithGasParams = {
...transaction,
chainId: this.#network.chainId,
};

if (!txWithGasParams.maxFeePerGas && !txWithGasParams.gasPrice) {
const feeData = await this.#publicClient.estimateFeesPerGas();
txWithGasParams.maxFeePerGas = feeData.maxFeePerGas;
txWithGasParams.maxPriorityFeePerGas = feeData.maxPriorityFeePerGas;
}

if (!txWithGasParams.gas) {
try {
txWithGasParams.gas = await this.#publicClient.estimateGas({
account: this.#serverAccount.address as Address,
...txWithGasParams,
});
} catch (error) {
console.warn("Failed to estimate gas, continuing without gas estimation", error);
}
}
const result = await this.#cdp.evm.sendTransaction({
address: this.#serverAccount.address,
transaction: serializeTransaction(transaction as TransactionSerializable),
transaction: serializeTransaction(txWithGasParams as TransactionSerializable),
network: this.#getCdpSdkNetwork(),
});
return result.transactionHash;
Expand Down
17 changes: 17 additions & 0 deletions typescript/agentkit/src/wallet-providers/cdpV2Shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,20 @@ export interface WalletProviderWithClient {
*/
getClient(): CdpClient;
}

/**
* Type guard to check if a wallet provider implements WalletProviderWithClient interface.
*
* @param provider - The provider to check
* @returns True if the provider implements WalletProviderWithClient
*/
export function isWalletProviderWithClient(
provider: unknown,
): provider is WalletProviderWithClient {
return (
provider !== null &&
typeof provider === "object" &&
"getClient" in provider &&
typeof (provider as WalletProviderWithClient).getClient === "function"
);
}
Loading