-
Notifications
You must be signed in to change notification settings - Fork 756
feat: add zeroDevWalletProvider #665
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
CarsonRoscoe
merged 14 commits into
coinbase:main
from
zerodevapp:zerodev-wallet-provider
Apr 18, 2025
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
b66d0c4
Implement ZeroDev wallet provider and an example
derekchiang 21521ee
fix: zerodev example deps
jstinhw 8e28cab
feat: use viem/cdp signer in zerodev example
jstinhw 16fdae9
fix: use hashMessage from viem in cdpWalletProvider
jstinhw 087f03e
fix: chain abstraction related prompt
jstinhw d61df9f
test: add zerodevWalletProvider test
jstinhw e26e5f1
feat: add privy as signer to zeroDevWalletProvider example
jstinhw b112709
chore: changeset
jstinhw 54a6034
chore: fix nits
jstinhw e78cbb1
doc: add zeroDevWalletProvider to agentkit readme
jstinhw 87a7685
doc: update README for zeroDevWalletProvider
derekchiang 7e8d615
feat: add zeroDevWalletActionProvider
jstinhw 10025d6
feat: add toSigner to evmWalletProvider
jstinhw 23c9b79
fix: zeroDevWalletProvider network default to base-sepolia
jstinhw File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| "@coinbase/agentkit": minor | ||
| --- | ||
|
|
||
| Added ZeroDevWalletProvider powered by ZeroDev smart account | ||
|
|
||
| This change introduced a new wallet provider, `ZeroDevWalletProvider` which allows AgentKit to use ZeroDev's chain-abstracted smart account with any EvmWalletProvider like cdpWalletProvider or privyEvmWalletProvider as the signer. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
typescript/agentkit/src/action-providers/zerodev/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| # ZeroDev Action Provider | ||
|
|
||
| This directory contains the **ZeroDevWalletActionProvider** implementation, which provides actions to interact with the **ZeroDev** wallet services and chain abstraction features. | ||
|
|
||
| ## Directory Structure | ||
|
|
||
| ``` | ||
| zerodev/ | ||
| ├── zeroDevWalletActionProvider.ts # Provider for ZeroDev Wallet operations | ||
| ├── zeroDevWalletActionProvider.test.ts # Tests for ZeroDev Wallet provider | ||
| ├── schemas.ts # Action schemas for ZeroDev operations | ||
| ├── index.ts # Main exports | ||
| └── README.md # This file | ||
| ``` | ||
|
|
||
| ## Actions | ||
|
|
||
| ### ZeroDev Wallet Actions | ||
|
|
||
| - `get_cab`: Retrieves chain abstracted balances (CAB) for specified tokens across multiple networks | ||
|
|
||
| - Input parameters: | ||
| - `tokenTickers`: Array of token symbols (e.g., ["ETH", "USDC"]) | ||
| - `networks` (optional): Array of network IDs to check balances on | ||
| - `networkType` (optional): Filter networks by type ("mainnet" or "testnet") | ||
| - Returns aggregated balances across all specified networks for each token ticker | ||
|
|
||
| ## Adding New Actions | ||
|
|
||
| To add new ZeroDev actions: | ||
|
|
||
| 1. Define your action schema in `schemas.ts` | ||
| 2. Implement the action in `zeroDevWalletActionProvider.ts` | ||
| 3. Add corresponding tests in `zeroDevWalletActionProvider.test.ts` | ||
|
|
||
| ## Network Support | ||
|
|
||
| The ZeroDev provider supports all EVM-compatible networks, including: | ||
|
|
||
| - Ethereum (Mainnet) | ||
| - Base (Mainnet) | ||
| - Optimism (Mainnet) | ||
| - Arbitrum (Mainnet) | ||
| - Polygon (Mainnet) | ||
| - Bsc (Mainnet) | ||
| - Avalanche (Mainnet) | ||
|
|
||
| ## Notes | ||
|
|
||
| - The ZeroDev provider requires proper configuration of the ZeroDevWalletProvider | ||
| - Chain abstraction features work across all supported EVM networks | ||
| - The `get_cab` action provides a unified view of token balances across multiple chains | ||
|
|
||
| For more information on **ZeroDev**, visit the [ZeroDev Documentation](https://docs.zerodev.app/). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export * from "./zeroDevWalletActionProvider"; |
19 changes: 19 additions & 0 deletions
19
typescript/agentkit/src/action-providers/zerodev/schemas.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import { z } from "zod"; | ||
|
|
||
| /** | ||
| * Input schema for get CAB action. | ||
| */ | ||
| export const GetCABSchema = z.discriminatedUnion("type", [ | ||
| z.object({ | ||
| type: z.literal("networkFilter"), | ||
| tokenTickers: z.array(z.string()).optional(), | ||
| networks: z.array(z.number()).describe("The networks to get the balance for."), | ||
| }), | ||
| z.object({ | ||
| type: z.literal("networkType"), | ||
| tokenTickers: z.array(z.string()).optional(), | ||
| networkType: z | ||
| .enum(["mainnet", "testnet"]) | ||
| .describe("The type of network to get the balance for."), | ||
| }), | ||
| ]); |
139 changes: 139 additions & 0 deletions
139
typescript/agentkit/src/action-providers/zerodev/zeroDevWalletActionProvider.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| import { ZeroDevWalletProvider } from "../../wallet-providers"; | ||
| import { ZeroDevWalletActionProvider } from "./zeroDevWalletActionProvider"; | ||
| import { GetCABSchema } from "./schemas"; | ||
| import { type GetCABResult } from "@zerodev/intent"; | ||
|
|
||
| describe("ZeroDev Wallet Action Provider Input Schemas", () => { | ||
| describe("Get CAB Schema", () => { | ||
| it("should successfully parse valid input with network type", () => { | ||
| const validInput = { | ||
| type: "networkType" as const, | ||
| tokenTickers: ["ETH", "USDC"], | ||
| networkType: "mainnet" as const, | ||
| }; | ||
|
|
||
| const result = GetCABSchema.safeParse(validInput); | ||
|
|
||
| expect(result.success).toBe(true); | ||
| expect(result.data).toEqual(validInput); | ||
| }); | ||
|
|
||
| it("should successfully parse valid input with network filter", () => { | ||
| const validInput = { | ||
| type: "networkFilter" as const, | ||
| tokenTickers: ["ETH", "USDC"], | ||
| networks: [1, 8453], // ethereum and base network IDs | ||
| }; | ||
|
|
||
| const result = GetCABSchema.safeParse(validInput); | ||
|
|
||
| expect(result.success).toBe(true); | ||
| expect(result.data).toEqual(validInput); | ||
| }); | ||
|
|
||
| it("should successfully parse input with optional tokenTickers omitted", () => { | ||
| const validInput = { | ||
| type: "networkType" as const, | ||
| networkType: "mainnet" as const, | ||
| }; | ||
|
|
||
| const result = GetCABSchema.safeParse(validInput); | ||
|
|
||
| expect(result.success).toBe(true); | ||
| expect(result.data).toEqual(validInput); | ||
| }); | ||
|
|
||
| it("should fail parsing empty input", () => { | ||
| const emptyInput = {}; | ||
| const result = GetCABSchema.safeParse(emptyInput); | ||
|
|
||
| expect(result.success).toBe(false); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| describe("ZeroDev Wallet Action Provider", () => { | ||
| let actionProvider: ZeroDevWalletActionProvider; | ||
| let mockWallet: jest.Mocked<ZeroDevWalletProvider>; | ||
|
|
||
| beforeEach(() => { | ||
| // Reset all mocks before each test | ||
| jest.clearAllMocks(); | ||
|
|
||
| actionProvider = new ZeroDevWalletActionProvider(); | ||
| mockWallet = { | ||
| getCAB: jest.fn(), | ||
| getAddress: jest.fn().mockReturnValue("0xe6b2af36b3bb8d47206a129ff11d5a2de2a63c83"), | ||
| getNetwork: jest.fn().mockReturnValue({ networkId: "ethereum-mainnet" }), | ||
| } as unknown as jest.Mocked<ZeroDevWalletProvider>; | ||
| }); | ||
|
|
||
| describe("getCAB", () => { | ||
| const MOCK_BALANCES = { | ||
| balance: BigInt(1000000000000000000), | ||
| tokenAddress: "0x1234567890123456789012345678901234567890" as `0x${string}`, | ||
| tokens: { | ||
| ETH: { | ||
| ethereum: "1.5", | ||
| base: "0.5", | ||
| }, | ||
| USDC: { | ||
| ethereum: "1000", | ||
| base: "500", | ||
| }, | ||
| }, | ||
| } as unknown as GetCABResult; | ||
|
|
||
| beforeEach(() => { | ||
| mockWallet.getCAB.mockResolvedValue(MOCK_BALANCES); | ||
| }); | ||
|
|
||
| it("should successfully get chain abstracted balances with network type", async () => { | ||
| const args = { | ||
| type: "networkType" as const, | ||
| tokenTickers: ["ETH", "USDC"], | ||
| networkType: "mainnet" as const, | ||
| }; | ||
|
|
||
| const result = await actionProvider.getCAB(mockWallet, args); | ||
|
|
||
| expect(mockWallet.getCAB).toHaveBeenCalledWith(args); | ||
| expect(result).toEqual(MOCK_BALANCES); | ||
| }); | ||
|
|
||
| it("should successfully get chain abstracted balances with network filter", async () => { | ||
| const args = { | ||
| type: "networkFilter" as const, | ||
| tokenTickers: ["ETH", "USDC"], | ||
| networks: [1, 8453], // ethereum and base network IDs | ||
| }; | ||
|
|
||
| const result = await actionProvider.getCAB(mockWallet, args); | ||
|
|
||
| expect(mockWallet.getCAB).toHaveBeenCalledWith(args); | ||
| expect(result).toEqual(MOCK_BALANCES); | ||
| }); | ||
|
|
||
| it("should handle errors when getting balances", async () => { | ||
| const args = { | ||
| type: "networkType" as const, | ||
| networkType: "mainnet" as const, | ||
| }; | ||
|
|
||
| const error = new Error("Failed to get balances"); | ||
| mockWallet.getCAB.mockRejectedValue(error); | ||
|
|
||
| await expect(actionProvider.getCAB(mockWallet, args)).rejects.toThrow(error); | ||
| }); | ||
| }); | ||
|
|
||
| describe("supportsNetwork", () => { | ||
| it("should return true when protocolFamily is evm", () => { | ||
| expect(actionProvider.supportsNetwork({ protocolFamily: "evm" })).toBe(true); | ||
| }); | ||
|
|
||
| it("should return false when protocolFamily is not evm", () => { | ||
| expect(actionProvider.supportsNetwork({ protocolFamily: "solana" })).toBe(false); | ||
| }); | ||
| }); | ||
| }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.