From 56efbb7db089ed6aec5eeb6ee6e25445509e781d Mon Sep 17 00:00:00 2001 From: Greg Skriloff <35093316+gskril@users.noreply.github.com> Date: Wed, 5 Feb 2025 03:17:34 -0500 Subject: [PATCH 1/3] Clean up Hex types and improve response types --- CONTRIBUTING-TYPESCRIPT.md | 2 +- .../basename/basenameActionProvider.test.ts | 4 +-- .../erc721/erc721ActionProvider.test.ts | 4 +-- .../erc721/erc721ActionProvider.ts | 4 +-- .../morpho/morphoActionProvider.test.ts | 8 ++--- .../morpho/morphoActionProvider.ts | 6 ++-- .../wallet/walletActionProvider.ts | 3 +- .../src/action-providers/wow/schemas.ts | 4 +-- .../src/action-providers/wow/uniswap/utils.ts | 22 ++++++------ .../src/action-providers/wow/utils.ts | 8 +++-- .../wow/wowActionProvider.test.ts | 10 +++--- .../action-providers/wow/wowActionProvider.ts | 8 ++--- typescript/agentkit/src/utils.test.ts | 8 ++--- typescript/agentkit/src/utils.ts | 6 ++-- .../src/wallet-providers/cdpWalletProvider.ts | 35 +++++++++---------- .../src/wallet-providers/evmWalletProvider.ts | 18 ++++++---- .../wallet-providers/viemWalletProvider.ts | 14 ++++---- .../src/wallet-providers/walletProvider.ts | 4 ++- 18 files changed, 89 insertions(+), 79 deletions(-) diff --git a/CONTRIBUTING-TYPESCRIPT.md b/CONTRIBUTING-TYPESCRIPT.md index 5b618f7a2..3bd062dcb 100644 --- a/CONTRIBUTING-TYPESCRIPT.md +++ b/CONTRIBUTING-TYPESCRIPT.md @@ -143,7 +143,7 @@ Do not use the contract address as the destination address. If you are unsure of }); const hash = await walletProvider.sendTransaction({ - to: args.contractAddress as `0x${string}`, + to: args.contractAddress as Hex, data, }); diff --git a/typescript/agentkit/src/action-providers/basename/basenameActionProvider.test.ts b/typescript/agentkit/src/action-providers/basename/basenameActionProvider.test.ts index 582461d82..8b44e2597 100644 --- a/typescript/agentkit/src/action-providers/basename/basenameActionProvider.test.ts +++ b/typescript/agentkit/src/action-providers/basename/basenameActionProvider.test.ts @@ -1,4 +1,4 @@ -import { encodeFunctionData, namehash, parseEther } from "viem"; +import { encodeFunctionData, namehash, parseEther, Hex } from "viem"; import { basenameActionProvider } from "./basenameActionProvider"; import { @@ -61,7 +61,7 @@ describe("Register Basename Action", () => { waitForTransactionReceipt: jest.fn(), } as unknown as jest.Mocked; - mockWallet.sendTransaction.mockResolvedValue("some-hash" as `0x${string}`); + mockWallet.sendTransaction.mockResolvedValue("some-hash" as Hex); mockWallet.waitForTransactionReceipt.mockResolvedValue({}); }); diff --git a/typescript/agentkit/src/action-providers/erc721/erc721ActionProvider.test.ts b/typescript/agentkit/src/action-providers/erc721/erc721ActionProvider.test.ts index 5fb518dec..0e104f728 100644 --- a/typescript/agentkit/src/action-providers/erc721/erc721ActionProvider.test.ts +++ b/typescript/agentkit/src/action-providers/erc721/erc721ActionProvider.test.ts @@ -1,4 +1,4 @@ -import { encodeFunctionData } from "viem"; +import { encodeFunctionData, Hex } from "viem"; import { erc721ActionProvider } from "./erc721ActionProvider"; import { ERC721_ABI } from "./constants"; import { EvmWalletProvider } from "../../wallet-providers"; @@ -22,7 +22,7 @@ describe("ERC721 Action Provider", () => { call: jest.fn(), } as unknown as jest.Mocked; - mockWallet.sendTransaction.mockResolvedValue("0xmockhash" as `0x${string}`); + mockWallet.sendTransaction.mockResolvedValue("0xmockhash" as Hex); mockWallet.waitForTransactionReceipt.mockResolvedValue({}); }); diff --git a/typescript/agentkit/src/action-providers/erc721/erc721ActionProvider.ts b/typescript/agentkit/src/action-providers/erc721/erc721ActionProvider.ts index 007eb0890..69575e13c 100644 --- a/typescript/agentkit/src/action-providers/erc721/erc721ActionProvider.ts +++ b/typescript/agentkit/src/action-providers/erc721/erc721ActionProvider.ts @@ -43,7 +43,7 @@ Do not use the contract address as the destination address. If you are unsure of }); const hash = await walletProvider.sendTransaction({ - to: args.contractAddress as `0x${string}`, + to: args.contractAddress as Hex, data, }); @@ -91,7 +91,7 @@ Important notes: }); const hash = await walletProvider.sendTransaction({ - to: args.contractAddress as `0x${string}`, + to: args.contractAddress as Hex, data, }); diff --git a/typescript/agentkit/src/action-providers/morpho/morphoActionProvider.test.ts b/typescript/agentkit/src/action-providers/morpho/morphoActionProvider.test.ts index dac1d7dec..e297648ef 100644 --- a/typescript/agentkit/src/action-providers/morpho/morphoActionProvider.test.ts +++ b/typescript/agentkit/src/action-providers/morpho/morphoActionProvider.test.ts @@ -1,4 +1,4 @@ -import { encodeFunctionData, parseEther } from "viem"; +import { encodeFunctionData, parseEther, Hex } from "viem"; import { EvmWalletProvider } from "../../wallet-providers"; import { approve } from "../../utils"; import { MorphoActionProvider } from "./morphoActionProvider"; @@ -23,7 +23,7 @@ describe("Morpho Action Provider", () => { mockWallet = { getAddress: jest.fn().mockReturnValue(MOCK_RECEIVER_ID), getNetwork: jest.fn().mockReturnValue({ protocolFamily: "evm", networkId: "1" }), - sendTransaction: jest.fn().mockResolvedValue(MOCK_TX_HASH as `0x${string}`), + sendTransaction: jest.fn().mockResolvedValue(MOCK_TX_HASH as Hex), waitForTransactionReceipt: jest.fn().mockResolvedValue(MOCK_RECEIPT), } as unknown as jest.Mocked; @@ -51,7 +51,7 @@ describe("Morpho Action Provider", () => { ); expect(mockWallet.sendTransaction).toHaveBeenCalledWith({ - to: MOCK_VAULT_ADDRESS as `0x${string}`, + to: MOCK_VAULT_ADDRESS as Hex, data: encodeFunctionData({ abi: METAMORPHO_ABI, functionName: "deposit", @@ -92,7 +92,7 @@ describe("Morpho Action Provider", () => { const response = await actionProvider.withdraw(mockWallet, args); expect(mockWallet.sendTransaction).toHaveBeenCalledWith({ - to: MOCK_VAULT_ADDRESS as `0x${string}`, + to: MOCK_VAULT_ADDRESS as Hex, data: encodeFunctionData({ abi: METAMORPHO_ABI, functionName: "withdraw", diff --git a/typescript/agentkit/src/action-providers/morpho/morphoActionProvider.ts b/typescript/agentkit/src/action-providers/morpho/morphoActionProvider.ts index 85a5a8633..a16b94e64 100644 --- a/typescript/agentkit/src/action-providers/morpho/morphoActionProvider.ts +++ b/typescript/agentkit/src/action-providers/morpho/morphoActionProvider.ts @@ -1,6 +1,6 @@ import { z } from "zod"; import { Decimal } from "decimal.js"; -import { encodeFunctionData, parseEther } from "viem"; +import { encodeFunctionData, parseEther, Hex } from "viem"; import { ActionProvider } from "../actionProvider"; import { EvmWalletProvider } from "../../wallet-providers"; @@ -78,7 +78,7 @@ Important notes: }); const txHash = await wallet.sendTransaction({ - to: args.vaultAddress as `0x${string}`, + to: args.vaultAddress as Hex, data, }); @@ -121,7 +121,7 @@ This tool allows withdrawing assets from a Morpho Vault. It takes: }); const txHash = await wallet.sendTransaction({ - to: args.vaultAddress as `0x${string}`, + to: args.vaultAddress as Hex, data, }); diff --git a/typescript/agentkit/src/action-providers/wallet/walletActionProvider.ts b/typescript/agentkit/src/action-providers/wallet/walletActionProvider.ts index a066e0612..06ef9944f 100644 --- a/typescript/agentkit/src/action-providers/wallet/walletActionProvider.ts +++ b/typescript/agentkit/src/action-providers/wallet/walletActionProvider.ts @@ -1,4 +1,5 @@ import { Decimal } from "decimal.js"; +import { Hex } from "viem"; import { z } from "zod"; import { CreateAction } from "../actionDecorator"; @@ -92,7 +93,7 @@ Important notes: args: z.infer, ): Promise { try { - const result = await walletProvider.nativeTransfer(args.to as `0x${string}`, args.value); + const result = await walletProvider.nativeTransfer(args.to as Hex, args.value); return `Transferred ${args.value} ETH to ${args.to}.\nTransaction hash: ${result}`; } catch (error) { diff --git a/typescript/agentkit/src/action-providers/wow/schemas.ts b/typescript/agentkit/src/action-providers/wow/schemas.ts index 4a0196c07..db9bbdd4c 100644 --- a/typescript/agentkit/src/action-providers/wow/schemas.ts +++ b/typescript/agentkit/src/action-providers/wow/schemas.ts @@ -1,7 +1,7 @@ import { z } from "zod"; -import { isAddress } from "viem"; +import { isAddress, Hex } from "viem"; -const ethereumAddress = z.custom<`0x${string}`>( +const ethereumAddress = z.custom( val => typeof val === "string" && isAddress(val), "Invalid address", ); diff --git a/typescript/agentkit/src/action-providers/wow/uniswap/utils.ts b/typescript/agentkit/src/action-providers/wow/uniswap/utils.ts index c725d0e18..46d6928b0 100644 --- a/typescript/agentkit/src/action-providers/wow/uniswap/utils.ts +++ b/typescript/agentkit/src/action-providers/wow/uniswap/utils.ts @@ -1,4 +1,4 @@ -import { formatEther, getAddress } from "viem"; +import { formatEther, getAddress, Hex } from "viem"; import { EvmWalletProvider } from "../../../wallet-providers"; import { ADDRESSES, WOW_ABI } from "../constants"; import { UNISWAP_QUOTER_ABI, UNISWAP_V3_ABI } from "./constants"; @@ -66,31 +66,31 @@ export async function getPoolInfo( try { const results = await Promise.all([ wallet.readContract({ - address: poolAddress as `0x${string}`, + address: poolAddress as Hex, functionName: "token0", args: [], abi: UNISWAP_V3_ABI, }), wallet.readContract({ - address: poolAddress as `0x${string}`, + address: poolAddress as Hex, functionName: "token1", args: [], abi: UNISWAP_V3_ABI, }), wallet.readContract({ - address: poolAddress as `0x${string}`, + address: poolAddress as Hex, functionName: "fee", args: [], abi: UNISWAP_V3_ABI, }), wallet.readContract({ - address: poolAddress as `0x${string}`, + address: poolAddress as Hex, functionName: "liquidity", args: [], abi: UNISWAP_V3_ABI, }), wallet.readContract({ - address: poolAddress as `0x${string}`, + address: poolAddress as Hex, functionName: "slot0", args: [], abi: UNISWAP_V3_ABI, @@ -101,13 +101,13 @@ export async function getPoolInfo( const [balance0, balance1] = await Promise.all([ wallet.readContract({ - address: token0Result as `0x${string}`, + address: token0Result as Hex, functionName: "balanceOf", args: [poolAddress], abi: WOW_ABI, }), wallet.readContract({ - address: token1Result as `0x${string}`, + address: token1Result as Hex, functionName: "balanceOf", args: [poolAddress], abi: WOW_ABI, @@ -148,7 +148,7 @@ export async function exactInputSingle( try { const networkId = wallet.getNetwork().networkId!; const amount = await wallet.readContract({ - address: ADDRESSES[networkId].UniswapQuoter as `0x${string}`, + address: ADDRESSES[networkId].UniswapQuoter as Hex, functionName: "quoteExactInputSingle", args: [ { @@ -262,7 +262,7 @@ export async function getHasGraduated( tokenAddress: string, ): Promise { const marketType = await wallet.readContract({ - address: tokenAddress as `0x${string}`, + address: tokenAddress as Hex, functionName: "marketType", args: [], abi: WOW_ABI, @@ -282,7 +282,7 @@ export async function getPoolAddress( tokenAddress: string, ): Promise { const poolAddress = await wallet.readContract({ - address: tokenAddress as `0x${string}`, + address: tokenAddress as Hex, functionName: "poolAddress", args: [], abi: WOW_ABI, diff --git a/typescript/agentkit/src/action-providers/wow/utils.ts b/typescript/agentkit/src/action-providers/wow/utils.ts index 811d25731..4ea400ea2 100644 --- a/typescript/agentkit/src/action-providers/wow/utils.ts +++ b/typescript/agentkit/src/action-providers/wow/utils.ts @@ -1,3 +1,5 @@ +import { Hex } from "viem"; + import { EvmWalletProvider } from "../../wallet-providers"; import { WOW_ABI } from "./constants"; import { getHasGraduated, getUniswapQuote } from "./uniswap/utils"; @@ -14,7 +16,7 @@ export async function getCurrentSupply( tokenAddress: string, ): Promise { const supply = await wallet.readContract({ - address: tokenAddress as `0x${string}`, + address: tokenAddress as Hex, abi: WOW_ABI, functionName: "totalSupply", args: [], @@ -42,7 +44,7 @@ export async function getBuyQuote( hasGraduated ? (await getUniswapQuote(wallet, tokenAddress, Number(amountEthInWei), "buy")).amountOut : await wallet.readContract({ - address: tokenAddress as `0x${string}`, + address: tokenAddress as Hex, abi: WOW_ABI, functionName: "getEthBuyQuote", args: [amountEthInWei], @@ -71,7 +73,7 @@ export async function getSellQuote( hasGraduated ? (await getUniswapQuote(wallet, tokenAddress, Number(amountTokensInWei), "sell")).amountOut : await wallet.readContract({ - address: tokenAddress as `0x${string}`, + address: tokenAddress as Hex, abi: WOW_ABI, functionName: "getTokenSellQuote", args: [amountTokensInWei], diff --git a/typescript/agentkit/src/action-providers/wow/wowActionProvider.test.ts b/typescript/agentkit/src/action-providers/wow/wowActionProvider.test.ts index 08948f632..baefdce9f 100644 --- a/typescript/agentkit/src/action-providers/wow/wowActionProvider.test.ts +++ b/typescript/agentkit/src/action-providers/wow/wowActionProvider.test.ts @@ -1,4 +1,4 @@ -import { encodeFunctionData } from "viem"; +import { encodeFunctionData, Hex } from "viem"; import { EvmWalletProvider } from "../../wallet-providers"; import { WowActionProvider } from "./wowActionProvider"; import { WOW_ABI, WOW_FACTORY_ABI, GENERIC_TOKEN_METADATA_URI } from "./constants"; @@ -16,8 +16,8 @@ jest.mock("./uniswap/utils", () => ({ })); describe("WowActionProvider", () => { - const MOCK_CONTRACT_ADDRESS = "0x1234567890123456789012345678901234567890" as `0x${string}`; - const INVALID_ADDRESS = "0xinvalid" as `0x${string}`; + const MOCK_CONTRACT_ADDRESS = "0x1234567890123456789012345678901234567890" as Hex; + const INVALID_ADDRESS = "0xinvalid" as Hex; const MOCK_AMOUNT_ETH_IN_WEI = BigInt("100000000000000000"); const INVALID_WEI = "1.5"; // Wei amounts can't have decimals const MOCK_AMOUNT_TOKENS_IN_WEI = BigInt("1000000000000000000"); @@ -26,7 +26,7 @@ describe("WowActionProvider", () => { const MOCK_URI = "ipfs://QmY1GqprFYvojCcUEKgqHeDj9uhZD9jmYGrQTfA9vAE78J"; const INVALID_URI = "not-a-url"; const MOCK_TX_HASH = "0xabcdef1234567890"; - const MOCK_ADDRESS = "0x9876543210987654321098765432109876543210" as `0x${string}`; + const MOCK_ADDRESS = "0x9876543210987654321098765432109876543210" as Hex; let provider: WowActionProvider; let mockWallet: jest.Mocked; @@ -35,7 +35,7 @@ describe("WowActionProvider", () => { mockWallet = { getAddress: jest.fn().mockReturnValue(MOCK_ADDRESS), getNetwork: jest.fn().mockReturnValue({ protocolFamily: "evm", networkId: "base-sepolia" }), - sendTransaction: jest.fn().mockResolvedValue(MOCK_TX_HASH as `0x${string}`), + sendTransaction: jest.fn().mockResolvedValue(MOCK_TX_HASH as Hex), waitForTransactionReceipt: jest.fn().mockResolvedValue({}), readContract: jest.fn(), } as unknown as jest.Mocked; diff --git a/typescript/agentkit/src/action-providers/wow/wowActionProvider.ts b/typescript/agentkit/src/action-providers/wow/wowActionProvider.ts index 98b983a8c..9a55fb378 100644 --- a/typescript/agentkit/src/action-providers/wow/wowActionProvider.ts +++ b/typescript/agentkit/src/action-providers/wow/wowActionProvider.ts @@ -12,7 +12,7 @@ import { } from "./constants"; import { getBuyQuote, getSellQuote } from "./utils"; import { getHasGraduated } from "./uniswap/utils"; -import { encodeFunctionData } from "viem"; +import { encodeFunctionData, Hex } from "viem"; import { WowBuyTokenInput, WowCreateTokenInput, WowSellTokenInput } from "./schemas"; /** @@ -81,7 +81,7 @@ Important notes: }); const txHash = await wallet.sendTransaction({ - to: args.contractAddress as `0x${string}`, + to: args.contractAddress as Hex, data, value: BigInt(args.amountEthInWei), }); @@ -139,7 +139,7 @@ Important notes: }); const txHash = await wallet.sendTransaction({ - to: factoryAddress as `0x${string}`, + to: factoryAddress as Hex, data, }); @@ -206,7 +206,7 @@ Important notes: }); const txHash = await wallet.sendTransaction({ - to: args.contractAddress as `0x${string}`, + to: args.contractAddress as Hex, data, }); diff --git a/typescript/agentkit/src/utils.test.ts b/typescript/agentkit/src/utils.test.ts index 5475830e1..634aa0cfd 100644 --- a/typescript/agentkit/src/utils.test.ts +++ b/typescript/agentkit/src/utils.test.ts @@ -1,4 +1,4 @@ -import { encodeFunctionData } from "viem"; +import { encodeFunctionData, Hex } from "viem"; import { EvmWalletProvider } from "./wallet-providers"; import { approve } from "./utils"; @@ -14,7 +14,7 @@ describe("utils", () => { beforeEach(() => { mockWallet = { - sendTransaction: jest.fn().mockResolvedValue(MOCK_TX_HASH as `0x${string}`), + sendTransaction: jest.fn().mockResolvedValue(MOCK_TX_HASH as Hex), waitForTransactionReceipt: jest.fn().mockResolvedValue(MOCK_RECEIPT), } as unknown as jest.Mocked; }); @@ -28,7 +28,7 @@ describe("utils", () => { ); expect(mockWallet.sendTransaction).toHaveBeenCalledWith({ - to: MOCK_TOKEN_ADDRESS as `0x${string}`, + to: MOCK_TOKEN_ADDRESS as Hex, data: encodeFunctionData({ abi: [ { @@ -43,7 +43,7 @@ describe("utils", () => { }, ], functionName: "approve", - args: [MOCK_SPENDER_ADDRESS as `0x${string}`, MOCK_AMOUNT], + args: [MOCK_SPENDER_ADDRESS as Hex, MOCK_AMOUNT], }), }); diff --git a/typescript/agentkit/src/utils.ts b/typescript/agentkit/src/utils.ts index a7e07141c..1aa983e48 100644 --- a/typescript/agentkit/src/utils.ts +++ b/typescript/agentkit/src/utils.ts @@ -1,4 +1,4 @@ -import { encodeFunctionData } from "viem"; +import { encodeFunctionData, Hex } from "viem"; import { EvmWalletProvider } from "./wallet-providers"; const ERC20_ABI = [ @@ -33,11 +33,11 @@ export async function approve( const data = encodeFunctionData({ abi: ERC20_ABI, functionName: "approve", - args: [spenderAddress as `0x${string}`, amount], + args: [spenderAddress as Hex, amount], }); const txHash = await wallet.sendTransaction({ - to: tokenAddress as `0x${string}`, + to: tokenAddress as Hex, data, }); diff --git a/typescript/agentkit/src/wallet-providers/cdpWalletProvider.ts b/typescript/agentkit/src/wallet-providers/cdpWalletProvider.ts index 2ffbcadc6..1b7b732a0 100644 --- a/typescript/agentkit/src/wallet-providers/cdpWalletProvider.ts +++ b/typescript/agentkit/src/wallet-providers/cdpWalletProvider.ts @@ -5,11 +5,13 @@ import { ReadContractReturnType, serializeTransaction, TransactionRequest, + TransactionReceipt, TransactionSerializable, http, keccak256, Signature, PublicClient, + Hex, } from "viem"; import { EvmWalletProvider } from "./evmWalletProvider"; import { Network } from "../network"; @@ -167,7 +169,7 @@ export class CdpWalletProvider extends EvmWalletProvider { * @param message - The message to sign. * @returns The signed message. */ - async signMessage(message: string): Promise<`0x${string}`> { + async signMessage(message: string): Promise { if (!this.#cdpWallet) { throw new Error("Wallet not initialized"); } @@ -175,7 +177,7 @@ export class CdpWalletProvider extends EvmWalletProvider { const messageHash = hashMessage(message); const payload = await this.#cdpWallet.createPayloadSignature(messageHash); - return payload.getSignature() as `0x${string}`; + return payload.getSignature() as Hex; } /** @@ -185,7 +187,7 @@ export class CdpWalletProvider extends EvmWalletProvider { * @returns The signed typed data object. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any - async signTypedData(typedData: any): Promise<`0x${string}`> { + async signTypedData(typedData: any): Promise { if (!this.#cdpWallet) { throw new Error("Wallet not initialized"); } @@ -198,7 +200,7 @@ export class CdpWalletProvider extends EvmWalletProvider { const payload = await this.#cdpWallet.createPayloadSignature(messageHash); - return payload.getSignature() as `0x${string}`; + return payload.getSignature() as Hex; } /** @@ -207,7 +209,7 @@ export class CdpWalletProvider extends EvmWalletProvider { * @param transaction - The transaction to sign. * @returns The signed transaction. */ - async signTransaction(transaction: TransactionRequest): Promise<`0x${string}`> { + async signTransaction(transaction: TransactionRequest): Promise { if (!this.#cdpWallet) { throw new Error("Wallet not initialized"); } @@ -217,7 +219,7 @@ export class CdpWalletProvider extends EvmWalletProvider { const payload = await this.#cdpWallet.createPayloadSignature(transactionHash); - return payload.getSignature() as `0x${string}`; + return payload.getSignature() as Hex; } /** @@ -226,7 +228,7 @@ export class CdpWalletProvider extends EvmWalletProvider { * @param transaction - The transaction to send. * @returns The hash of the transaction. */ - async sendTransaction(transaction: TransactionRequest): Promise<`0x${string}`> { + async sendTransaction(transaction: TransactionRequest): Promise { if (!this.#cdpWallet) { throw new Error("Wallet not initialized"); } @@ -247,7 +249,7 @@ export class CdpWalletProvider extends EvmWalletProvider { const tx = await externalAddress.broadcastExternalTransaction(signedPayload.slice(2)); - return tx.transactionHash as `0x${string}`; + return tx.transactionHash as Hex; } /** @@ -258,17 +260,13 @@ export class CdpWalletProvider extends EvmWalletProvider { * @param data - The data of the transaction. * @returns The prepared transaction. */ - async prepareTransaction( - to: `0x${string}`, - value: bigint, - data: `0x${string}`, - ): Promise { + async prepareTransaction(to: Hex, value: bigint, data: Hex): Promise { if (!this.#cdpWallet) { throw new Error("Wallet not initialized"); } const nonce = await this.#publicClient!.getTransactionCount({ - address: this.#address! as `0x${string}`, + address: this.#address! as Hex, }); const feeData = await this.#publicClient!.estimateFeesPerGas(); @@ -306,7 +304,7 @@ export class CdpWalletProvider extends EvmWalletProvider { */ async addSignatureAndSerialize( transaction: TransactionSerializable, - signature: `0x${string}`, + signature: Hex, ): Promise { // Decode the signature into its components const r = `0x${signature.slice(2, 66)}`; // First 32 bytes @@ -371,8 +369,7 @@ export class CdpWalletProvider extends EvmWalletProvider { * @param txHash - The hash of the transaction to wait for. * @returns The transaction receipt. */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - async waitForTransactionReceipt(txHash: `0x${string}`): Promise { + async waitForTransactionReceipt(txHash: Hex): Promise { return await this.#publicClient!.waitForTransactionReceipt({ hash: txHash }); } @@ -470,7 +467,7 @@ export class CdpWalletProvider extends EvmWalletProvider { * @param value - The amount to transfer in Wei. * @returns The transaction hash. */ - async nativeTransfer(to: `0x${string}`, value: string): Promise<`0x${string}`> { + async nativeTransfer(to: Hex, value: string): Promise { if (!this.#cdpWallet) { throw new Error("Wallet not initialized"); } @@ -488,7 +485,7 @@ export class CdpWalletProvider extends EvmWalletProvider { throw new Error("Transaction hash not found"); } - return result.getTransactionHash() as `0x${string}`; + return result.getTransactionHash() as Hex; } /** diff --git a/typescript/agentkit/src/wallet-providers/evmWalletProvider.ts b/typescript/agentkit/src/wallet-providers/evmWalletProvider.ts index f21744a49..6da35073c 100644 --- a/typescript/agentkit/src/wallet-providers/evmWalletProvider.ts +++ b/typescript/agentkit/src/wallet-providers/evmWalletProvider.ts @@ -2,7 +2,13 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { WalletProvider } from "./walletProvider"; -import { TransactionRequest, ReadContractParameters, ReadContractReturnType } from "viem"; +import { + TransactionRequest, + ReadContractParameters, + ReadContractReturnType, + TransactionReceipt, + Hex, +} from "viem"; /** * EvmWalletProvider is the abstract base class for all EVM wallet providers. @@ -16,7 +22,7 @@ export abstract class EvmWalletProvider extends WalletProvider { * @param message - The message to sign. * @returns The signed message. */ - abstract signMessage(message: string | Uint8Array): Promise<`0x${string}`>; + abstract signMessage(message: string | Uint8Array): Promise; /** * Sign a typed data. @@ -24,7 +30,7 @@ export abstract class EvmWalletProvider extends WalletProvider { * @param typedData - The typed data to sign. * @returns The signed typed data. */ - abstract signTypedData(typedData: any): Promise<`0x${string}`>; + abstract signTypedData(typedData: any): Promise; /** * Sign a transaction. @@ -32,7 +38,7 @@ export abstract class EvmWalletProvider extends WalletProvider { * @param transaction - The transaction to sign. * @returns The signed transaction. */ - abstract signTransaction(transaction: TransactionRequest): Promise<`0x${string}`>; + abstract signTransaction(transaction: TransactionRequest): Promise; /** * Send a transaction. @@ -40,7 +46,7 @@ export abstract class EvmWalletProvider extends WalletProvider { * @param transaction - The transaction to send. * @returns The transaction hash. */ - abstract sendTransaction(transaction: TransactionRequest): Promise<`0x${string}`>; + abstract sendTransaction(transaction: TransactionRequest): Promise; /** * Wait for a transaction receipt. @@ -48,7 +54,7 @@ export abstract class EvmWalletProvider extends WalletProvider { * @param txHash - The transaction hash. * @returns The transaction receipt. */ - abstract waitForTransactionReceipt(txHash: `0x${string}`): Promise; + abstract waitForTransactionReceipt(txHash: Hex): Promise; /** * Read a contract. diff --git a/typescript/agentkit/src/wallet-providers/viemWalletProvider.ts b/typescript/agentkit/src/wallet-providers/viemWalletProvider.ts index b2291cb77..d85dee4c9 100644 --- a/typescript/agentkit/src/wallet-providers/viemWalletProvider.ts +++ b/typescript/agentkit/src/wallet-providers/viemWalletProvider.ts @@ -10,6 +10,8 @@ import { ReadContractParameters, ReadContractReturnType, parseEther, + Hex, + TransactionReceipt, } from "viem"; import { EvmWalletProvider } from "./evmWalletProvider"; import { Network } from "../network"; @@ -42,7 +44,7 @@ export class ViemWalletProvider extends EvmWalletProvider { * @param message - The message to sign. * @returns The signed message. */ - async signMessage(message: string): Promise<`0x${string}`> { + async signMessage(message: string): Promise { const account = this.#walletClient.account; if (!account) { throw new Error("Account not found"); @@ -57,7 +59,7 @@ export class ViemWalletProvider extends EvmWalletProvider { * @param typedData - The typed data object to sign. * @returns The signed typed data object. */ - async signTypedData(typedData: any): Promise<`0x${string}`> { + async signTypedData(typedData: any): Promise { return this.#walletClient.signTypedData({ account: this.#walletClient.account!, domain: typedData.domain!, @@ -73,7 +75,7 @@ export class ViemWalletProvider extends EvmWalletProvider { * @param transaction - The transaction to sign. * @returns The signed transaction. */ - async signTransaction(transaction: TransactionRequest): Promise<`0x${string}`> { + async signTransaction(transaction: TransactionRequest): Promise { const txParams = { account: this.#walletClient.account!, to: transaction.to, @@ -91,7 +93,7 @@ export class ViemWalletProvider extends EvmWalletProvider { * @param transaction - The transaction to send. * @returns The hash of the transaction. */ - async sendTransaction(transaction: TransactionRequest): Promise<`0x${string}`> { + async sendTransaction(transaction: TransactionRequest): Promise { const account = this.#walletClient.account; if (!account) { throw new Error("Account not found"); @@ -164,7 +166,7 @@ export class ViemWalletProvider extends EvmWalletProvider { * @param txHash - The hash of the transaction to wait for. * @returns The transaction receipt. */ - async waitForTransactionReceipt(txHash: `0x${string}`): Promise { + async waitForTransactionReceipt(txHash: Hex): Promise { return await this.#publicClient.waitForTransactionReceipt({ hash: txHash }); } @@ -185,7 +187,7 @@ export class ViemWalletProvider extends EvmWalletProvider { * @param value - The amount to transfer in whole units (e.g. ETH) * @returns The transaction hash. */ - async nativeTransfer(to: `0x${string}`, value: string): Promise<`0x${string}`> { + async nativeTransfer(to: Hex, value: string): Promise { const atomicAmount = parseEther(value); const tx = await this.sendTransaction({ diff --git a/typescript/agentkit/src/wallet-providers/walletProvider.ts b/typescript/agentkit/src/wallet-providers/walletProvider.ts index f0e6a4688..36a6a8c08 100644 --- a/typescript/agentkit/src/wallet-providers/walletProvider.ts +++ b/typescript/agentkit/src/wallet-providers/walletProvider.ts @@ -1,3 +1,5 @@ +import { Hex } from "viem"; + import { Network } from "../network"; import { sendAnalyticsEvent } from "../analytics"; @@ -72,5 +74,5 @@ export abstract class WalletProvider { * @param value - The amount to transfer in whole units (e.g. ETH) * @returns The transaction hash. */ - abstract nativeTransfer(to: `0x${string}`, value: string): Promise<`0x${string}`>; + abstract nativeTransfer(to: Hex, value: string): Promise; } From 650409300dd3facfc6ef3e07b4d6d7577bf7097c Mon Sep 17 00:00:00 2001 From: Greg Skriloff <35093316+gskril@users.noreply.github.com> Date: Wed, 5 Feb 2025 17:16:42 -0500 Subject: [PATCH 2/3] Add method, export clients from ViemWalletProvider --- .../wallet-providers/viemWalletProvider.ts | 92 +++++++++++-------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/typescript/agentkit/src/wallet-providers/viemWalletProvider.ts b/typescript/agentkit/src/wallet-providers/viemWalletProvider.ts index d85dee4c9..7b3fb6fdc 100644 --- a/typescript/agentkit/src/wallet-providers/viemWalletProvider.ts +++ b/typescript/agentkit/src/wallet-providers/viemWalletProvider.ts @@ -1,17 +1,16 @@ -// TODO: Improve type safety -/* eslint-disable @typescript-eslint/no-explicit-any */ - import { - WalletClient as ViemWalletClient, - createPublicClient, - http, + WalletClient, TransactionRequest, - PublicClient as ViemPublicClient, + PublicClient, ReadContractParameters, ReadContractReturnType, parseEther, Hex, TransactionReceipt, + SimulateContractParameters, + SimulateContractReturnType, + publicActions, + HashTypedDataParameters, } from "viem"; import { EvmWalletProvider } from "./evmWalletProvider"; import { Network } from "../network"; @@ -21,21 +20,18 @@ import { CHAIN_ID_TO_NETWORK_ID } from "../network/network"; * A wallet provider that uses the Viem library. */ export class ViemWalletProvider extends EvmWalletProvider { - #walletClient: ViemWalletClient; - #publicClient: ViemPublicClient; + walletClient: WalletClient; + publicClient: PublicClient; /** * Constructs a new ViemWalletProvider. * * @param walletClient - The wallet client. */ - constructor(walletClient: ViemWalletClient) { + constructor(walletClient: WalletClient) { super(); - this.#walletClient = walletClient; - this.#publicClient = createPublicClient({ - chain: walletClient.chain, - transport: http(), - }); + this.walletClient = walletClient; + this.publicClient = walletClient.extend(publicActions) as PublicClient; } /** @@ -45,12 +41,12 @@ export class ViemWalletProvider extends EvmWalletProvider { * @returns The signed message. */ async signMessage(message: string): Promise { - const account = this.#walletClient.account; + const account = this.walletClient.account; if (!account) { throw new Error("Account not found"); } - return this.#walletClient.signMessage({ account, message }); + return this.walletClient.signMessage({ account, message }); } /** @@ -59,13 +55,17 @@ export class ViemWalletProvider extends EvmWalletProvider { * @param typedData - The typed data object to sign. * @returns The signed typed data object. */ - async signTypedData(typedData: any): Promise { - return this.#walletClient.signTypedData({ - account: this.#walletClient.account!, - domain: typedData.domain!, - types: typedData.types!, - primaryType: typedData.primaryType!, - message: typedData.message!, + async signTypedData(typedData: HashTypedDataParameters): Promise { + if (!this.walletClient.account) { + throw new Error("Account not found"); + } + + return this.walletClient.signTypedData({ + account: this.walletClient.account, + domain: typedData.domain, + types: typedData.types, + primaryType: typedData.primaryType, + message: typedData.message, }); } @@ -76,15 +76,19 @@ export class ViemWalletProvider extends EvmWalletProvider { * @returns The signed transaction. */ async signTransaction(transaction: TransactionRequest): Promise { + if (!this.walletClient.account) { + throw new Error("Account not found"); + } + const txParams = { - account: this.#walletClient.account!, + account: this.walletClient.account, to: transaction.to, value: transaction.value, data: transaction.data, - chain: this.#walletClient.chain, + chain: this.walletClient.chain, }; - return this.#walletClient.signTransaction(txParams); + return this.walletClient.signTransaction(txParams); } /** @@ -94,12 +98,12 @@ export class ViemWalletProvider extends EvmWalletProvider { * @returns The hash of the transaction. */ async sendTransaction(transaction: TransactionRequest): Promise { - const account = this.#walletClient.account; + const account = this.walletClient.account; if (!account) { throw new Error("Account not found"); } - const chain = this.#walletClient.chain; + const chain = this.walletClient.chain; if (!chain) { throw new Error("Chain not found"); } @@ -112,7 +116,7 @@ export class ViemWalletProvider extends EvmWalletProvider { value: transaction.value, }; - return this.#walletClient.sendTransaction(txParams); + return this.walletClient.sendTransaction(txParams); } /** @@ -121,7 +125,7 @@ export class ViemWalletProvider extends EvmWalletProvider { * @returns The address of the wallet. */ getAddress(): string { - return this.#walletClient.account?.address ?? ""; + return this.walletClient.account?.address ?? ""; } /** @@ -130,10 +134,14 @@ export class ViemWalletProvider extends EvmWalletProvider { * @returns The network of the wallet. */ getNetwork(): Network { + if (!this.walletClient.chain) { + throw new Error("Chain not found"); + } + return { protocolFamily: "evm" as const, - chainId: this.#walletClient.chain!.id! as any as string, - networkId: CHAIN_ID_TO_NETWORK_ID[this.#walletClient.chain!.id!], + chainId: this.walletClient.chain.id.toString(), + networkId: CHAIN_ID_TO_NETWORK_ID[this.walletClient.chain.id], }; } @@ -152,12 +160,12 @@ export class ViemWalletProvider extends EvmWalletProvider { * @returns The balance of the wallet. */ async getBalance(): Promise { - const account = this.#walletClient.account; + const account = this.walletClient.account; if (!account) { throw new Error("Account not found"); } - return this.#publicClient.getBalance({ address: account.address }); + return this.publicClient.getBalance({ address: account.address }); } /** @@ -167,7 +175,7 @@ export class ViemWalletProvider extends EvmWalletProvider { * @returns The transaction receipt. */ async waitForTransactionReceipt(txHash: Hex): Promise { - return await this.#publicClient.waitForTransactionReceipt({ hash: txHash }); + return await this.publicClient.waitForTransactionReceipt({ hash: txHash }); } /** @@ -177,7 +185,7 @@ export class ViemWalletProvider extends EvmWalletProvider { * @returns The response from the contract. */ async readContract(params: ReadContractParameters): Promise { - return this.#publicClient.readContract(params); + return this.publicClient.readContract(params); } /** @@ -203,4 +211,14 @@ export class ViemWalletProvider extends EvmWalletProvider { return receipt.transactionHash; } + + /** + * Simulates a contract interaction. + * + * @param params - The parameters to simulate the contract. + * @returns The response from the contract. + */ + async simulateContract(params: SimulateContractParameters): Promise { + return this.publicClient.simulateContract(params); + } } From c150e6ba4eaa735fa6f1ba257c5c5e297c56d157 Mon Sep 17 00:00:00 2001 From: Greg Skriloff <35093316+gskril@users.noreply.github.com> Date: Wed, 5 Feb 2025 17:17:02 -0500 Subject: [PATCH 3/3] Improve types on EvmWalletProvider --- .../agentkit/src/wallet-providers/evmWalletProvider.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/typescript/agentkit/src/wallet-providers/evmWalletProvider.ts b/typescript/agentkit/src/wallet-providers/evmWalletProvider.ts index 6da35073c..39b6968d1 100644 --- a/typescript/agentkit/src/wallet-providers/evmWalletProvider.ts +++ b/typescript/agentkit/src/wallet-providers/evmWalletProvider.ts @@ -1,6 +1,3 @@ -// TODO: Improve type safety -/* eslint-disable @typescript-eslint/no-explicit-any */ - import { WalletProvider } from "./walletProvider"; import { TransactionRequest, @@ -8,6 +5,7 @@ import { ReadContractReturnType, TransactionReceipt, Hex, + HashTypedDataParameters, } from "viem"; /** @@ -30,7 +28,7 @@ export abstract class EvmWalletProvider extends WalletProvider { * @param typedData - The typed data to sign. * @returns The signed typed data. */ - abstract signTypedData(typedData: any): Promise; + abstract signTypedData(typedData: HashTypedDataParameters): Promise; /** * Sign a transaction.