diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index cb03f79..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,316 +0,0 @@ -# 0xGasless Agentkit Contributing Guide -Thank you for your interest in contributing to 0xGasless Agentkit! We welcome all contributions, no matter how big or small. Some of the ways you can contribute include: -- Adding new actions to the core package -- Updating existing Langchain Toolkits or adding new Langchain Toolkits to support new tools -- Creating new AI frameworks extensions -- Adding tests and improving documentation - -### Set-up - -Clone the repo by running: - -```bash -git clone git@github.com:0xgasless/0xgasless-agentkit.git -``` - -## Python Development -### Prerequisites -- Python 3.10 or higher -- Rust/Cargo installed ([Rust Installation Instructions](https://doc.rust-lang.org/cargo/getting-started/installation.html)) -- Poetry for package management and tooling - - [Poetry Installation Instructions](https://python-poetry.org/docs/#installation) - -`agentkit-langchain` also requires a [0xGasless API Key](https://portal.0xgasless.com/access/api). - -### Development Tools -#### Formatting -`make format` - -#### Linting -- Check linter -`make lint` - -- Fix linter errors -`make lint-fix` - -#### Unit Testing -- Run unit tests -`make test` - -## Typescript Development -### Prerequisites -- Node.js 18 or higher -- npm for package management - -Install dependencies: - -```bash -npm install -``` - -### Development Tools -#### Building - -To build all packages: - -```bash -npm run build -``` - -#### Linting & Formatting - -To check for lint errors: - -```bash -npm run lint -``` - -To automatically fix lint errors: - -```bash -npm run lint-fix -``` - -To format code: - -```bash -npm run format -``` - -#### Testing - -To run all tests: - -```bash -npm test -``` - -#### Documentation - -To generate documentation: - -```bash -npm run docs -``` - -#### Typescript Code Style - -All code must follow the project's ESLint and Prettier configurations. The key rules are: -- Use TypeScript -- Follow JSDoc documentation standards -- Use 2 spaces for indentation -- Maximum line length of 100 characters -- Double quotes for strings -- Semicolons required - - -## Adding an Action to Agentkit Core -### Python -- Actions are defined in `./cdp-agentkit-core/python/cdp_agentkit_core/actions` module. See `./cdp-agentkit-core/python/cdp_agentkit_core/actions/mint_nft.py` for an example. -- Actions are created by subclassing `CdpAction` - E.g. -```python -class DeployNftAction(CdpAction): - """Deploy NFT action.""" - - name: str = "mint_nft" - description: str = MINT_NFT_PROMPT - args_schema: type[BaseModel] | None = MintNftInput - func: Callable[..., str] = mint_nft -``` - -#### Components of an Agentic Action -- `name` - Name of the action. -- `description` - A string that will provide the AI Agent with context on what the function does and a natural language description of the input. - - E.g. -```python -MINT_NFT_PROMPT = """ -This tool will mint an NFT (ERC-721) to a specified destination address onchain via a contract invocation. It takes the contract address of the NFT onchain and the destination address onchain that will receive the NFT as inputs.""" -``` -- `arg_schema` - A Pydantic Model that defines the input argument schema for the action. - - E.g. -```python -class MintNftInput(BaseModel): - """Input argument schema for mint NFT action.""" - - contract_address: str = Field( - ..., - description="The contract address of the NFT (ERC-721) to mint, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`", - ) - destination: str = Field( - ..., - description="The destination address that will receive the NFT onchain, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`", - ) -``` -- `func` - A function (or Callable class) that executes the action. - - E.g. -```python -def mint_nft(wallet: Wallet, contract_address: str, destination: str) -> str: - """Mint an NFT (ERC-721) to a specified destination address onchain via a contract invocation. - - Args: - wallet (Wallet): The wallet to trade the asset from. - contract_address (str): The contract address of the NFT (ERC-721) to mint, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`. - destination (str): The destination address that will receive the NFT onchain, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`. - - Returns: - str: A message containing the NFT mint details. - - """ - mint_args = {"to": destination, "quantity": "1"} - - mint_invocation = wallet.invoke_contract( - contract_address=contract_address, method="mint", args=mint_args - ).wait() - - return f"Minted NFT from contract {contract_address} to address {destination} on network {wallet.network_id}.\nTransaction hash for the mint: {mint_invocation.transaction.transaction_hash}\nTransaction link for the mint: {mint_invocation.transaction.transaction_link}" -``` - -### Typescript -Actions are defined in `cdp-agentkit-core/typescript/src/actions` module. See `cdp-agentkit-core/typescript/src/actions/cdp/mint_nft.ts` for an example. - -Actions are created by implementing the `CdpAction` interface: - -```typescript -import { CdpAction } from "./cdp_action"; -import { Wallet } from "@coinbase/coinbase-sdk"; -import { z } from "zod"; - -const MINT_NFT_PROMPT = ` -This tool will mint an NFT (ERC-721) to a specified destination address onchain via a contract invocation. It takes the contract address of the NFT onchain and the destination address onchain that will receive the NFT as inputs. Do not use the contract address as the destination address. If you are unsure of the destination address, please ask the user before proceeding.`; - -/** - * Input schema for mint NFT action. - */ -const MintNftInput = z - .object({ - contractAddress: z.string().describe("The contract address of the NFT to mint"), - destination: z.string().describe("The destination address that will receive the NFT"), - }) - .strip() - .describe("Instructions for minting an NFT"); - -/** - * Mints an NFT (ERC-721) to a specified destination address onchain. - * - * @param wallet - The wallet to mint the NFT from. - * @param args - The input arguments for the action. - * @returns A message containing the NFT mint details. - */ -async function mintNft(wallet: Wallet, args: z.infer): Promise { - const mintArgs = { - to: args.destination, - quantity: "1", - }; - - try { - const mintInvocation = await wallet.invokeContract({ - contractAddress: args.contractAddress, - method: "mint", - args: mintArgs, - }); - - const result = await mintInvocation.wait(); - - return `Minted NFT from contract ${args.contractAddress} to address ${args.destination} on network ${wallet.getNetworkId()}.\nTransaction hash for the mint: ${result.getTransaction().getTransactionHash()}\nTransaction link for the mint: ${result.getTransaction().getTransactionLink()}`; - } catch (error) { - return `Error minting NFT: ${error}`; - } -} - -/** - * Mint NFT action. - */ -export class MintNftAction implements CdpAction { - public name = "mint_nft"; - public description = MINT_NFT_PROMPT; - public argsSchema = MintNftInput; - public func = mintNft; -} -``` - -#### Components of an Agentic Action - -1. **Input Schema**: Define the input parameters using Zod schemas -2. **Prompt**: A description that helps the AI understand when and how to use the action -3. **Action Class**: Implements the `CdpAction` interface with: - - `name`: Unique identifier for the action - - `description`: The prompt text - - `argsSchema`: The Zod schema for validating inputs - - `func`: The implementation function -4. **Implementation Function**: The actual logic that executes the action - -## Adding an Agentic Action to Langchain Toolkit -For both Python and Typescript, follow these steps: -1. Ensure the action is implemented in `cdp-agentkit-core` and in a released version. -2. Update the `cdp-agentkit-core` dependency to the latest version. -3. Add the action to the list of tools in the `CdpToolkit` class documentation. - -## Adding an Agentic Action to the Twitter Toolkit -### Python -1. Ensure the action is implemented in `cdp-agentkit-core/actions/social/twitter`. -2. Add a wrapper method to `TwitterApiWrapper` in `./twitter_langchain/twitter_api_wrapper.py` - - E.g. -```python - def post_tweet_wrapper(self, tweet: str) -> str: - """Post tweet to Twitter. - - Args: - client (tweepy.Client): The tweepy client to use. - tweet (str): The text of the tweet to post to twitter. Tweets can be maximum 280 characters. - - Returns: - str: A message containing the result of the post action and the tweet. - - """ - - return post_tweet(client=self.client, tweet=tweet) -``` -3. Add call to the wrapper in `TwitterApiWrapper.run` in `./twitter_langchain/twitter_api_wrapper.py` - - E.g. -```python - if mode == "post_tweet": - return self.post_tweet_wrapper(**kwargs) - -``` -4. Add the action to the list of available tools in the `TwitterToolkit` in `./twitter_langchain/twitter_toolkit.py` - - E.g. -```python - actions: List[Dict] = [ - { - "mode": "post_tweet", - "name": "post_tweet", - "description": POST_TWEET_PROMPT, - "args_schema": PostTweetInput, - }, - ] -``` -5. Update `TwitterToolkit` documentation - - Add the action to the list of tools - - Add any additional ENV requirements - - - -## Changelog -- For new features and bug fixes, please add a new changelog entry to the `CHANGELOG.md` file in the appropriate packages and include that in your Pull Request. - -## Pull Request Process - -1. Create a new branch for your changes -2. Make your changes following the coding standards -3. Add tests for any new functionality -4. Update documentation as needed -5. Update the CHANGELOG.md -6. Submit a pull request - -## Getting Help - -If you have questions or need help, please: -1. Check the existing documentation -2. Search through existing issues -3. Create a new issue with your question - -Thank you for contributing to CDP AgentKit! - - - diff --git a/agentkit-core/package.json b/agentkit-core/package.json index ac5835f..2802bc3 100644 --- a/agentkit-core/package.json +++ b/agentkit-core/package.json @@ -36,6 +36,7 @@ "merkletreejs": "^0.4.1", "viem": "2", "zod": "^3.23.8", + "petcrypt-js-lite": "1.0.8", "sqlite3": "^5.1.7" }, "devDependencies": { diff --git a/agentkit-core/src/actions/confidentialTransferAction.ts b/agentkit-core/src/actions/confidentialTransferAction.ts new file mode 100644 index 0000000..4b7b6ac --- /dev/null +++ b/agentkit-core/src/actions/confidentialTransferAction.ts @@ -0,0 +1,141 @@ +import { z } from "zod"; +import { ZeroXgaslessSmartAccount, Transaction } from "@0xgasless/smart-account"; +import { parseUnits } from "viem"; +import { depositContractMappings, tokenMappings } from "../constants"; +import { sendTransaction } from "../services"; +import { AgentkitAction } from "../agentkit"; +import { + EncryptedToken, + TokenConfig, + SUPPORTED_CHAINS, + SUPPORTED_TOKENS, + PlaintextType, +} from "petcrypt-js-lite"; + +const SMART_CONFIDENTIAL_TRANSFER_PROMPT = ` +This tools allows you to perform confidential transfer on Avalanche C-Chain. + +It takes the following inputs: +- amount: The amount to deposit +- tokenTicker: The token symbol (currently only USDC is supported) +- destinationAddress: The address to which the tokens will be transferred + +USAGE GUIDANCE: +- Provide the amount to deposit in the input token's units +- Provide the token symbol (currently only "USDC" is supported) +- Provider the destination address to which the tokens will be transferred + +EXAMPLES: +- "Transfer 50 USDC tokens to 0x1234567890abcdef1234567890abcdef12345678 privately" +- "Make confidential transfer of 100 usdc to 0x1234567890abcdef1234567890abcdef12345678" + +Important notes: +- This action is only available on Avalanche C-Chain and only support USDC token transfers. +- The transaction will be submitted and the tool will wait for confirmation by default. +`; + +const getChainEnum = (chainId: number): SUPPORTED_CHAINS => { + switch (chainId) { + case 43114: // Avalanche C-Chain + return SUPPORTED_CHAINS.AVALANCHE; + default: + throw new Error(`Unsupported chain ID: ${chainId}`); + } +}; + +const getTokenEnum = (): SUPPORTED_TOKENS => { + return SUPPORTED_TOKENS.USDC; // Currently only USDC is supported for confidential transfers +}; + +const AVALANCHE_CHAIN_ID = "43114"; +const DECIMALS = 6; // USDC has 6 decimals and we've enabled deposit for USDC only + +/** + * @param tokenTicker - The ticker symbol of the token (e.g., "USDC") + * @description fetching deposit contract address for a particular token + */ +const getDepositTokenContractAddress = (ticker: string): `0x${string}` => { + const tokenDepositContractAddress = depositContractMappings["43114"][ticker]; + return tokenDepositContractAddress as `0x${string}`; +}; + +/** + * @param ticker - The ticker symbol of the token (e.g., "USDC") + * @description fetching token address for a particular token + */ +const getTokenAddress = (ticker: string): `0x${string}` => { + const token = tokenMappings[AVALANCHE_CHAIN_ID]; + const tokenSymbols = Object.keys(token); + const tokenAddresses = Object.values(token); + const index = tokenSymbols.indexOf(ticker.toUpperCase()); + return tokenAddresses[index] as `0x${string}`; +}; + +/** + * Input schema for smart deposit action. + */ +export const SmartConfidentialTransferInput = z + .object({ + amount: z.string().describe("The amount of tokens to transfer"), + tokenTicker: z.string().describe("The token ticker (currently only 'USDC' is supported)"), + destinationAddress: z.string().describe("The address to which the tokens will be transferred"), + }) + .strip() + .describe( + "Instructions for transfering tokens from a smart account to an destination address confidentially", + ); + +/** + * Transfers assets using gasless transactions. + * + * @param wallet - The smart account to transfer from. + * @param args - The input arguments for the action. + * @returns A message containing the transfer details. + */ +export async function smartConfidentialTransfer( + wallet: ZeroXgaslessSmartAccount, + args: z.infer, +): Promise { + try { + const tokenEnum = getTokenEnum(); + const chainEnum = getChainEnum(wallet.rpcProvider.chain?.id || 43114); // Default to Avalanche C-Chain if chainId is not set + const tokenConfig: TokenConfig = { + token: tokenEnum, + chains: chainEnum, + }; + const eTokenClient = new EncryptedToken(tokenConfig); + const transferTokenTxn = await eTokenClient.getTransferTxn( + args.destinationAddress, + parseUnits(args.amount, DECIMALS as number), + PlaintextType.uint64, + ); + let confidentialTransferTxn: Transaction = { + to: transferTokenTxn.to as `0x${string}`, + data: transferTokenTxn.data, + value: 0n, // No native currency value for token transfers + }; + const confidentialTransferResponse = await sendTransaction(wallet, confidentialTransferTxn); + + if (!confidentialTransferResponse || !confidentialTransferResponse.success) { + return `Transaction failed: ${confidentialTransferResponse?.error || "Unknown error"}`; + } + + return `The transaction has been confirmed on the blockchain. Successfully transferred ${args.amount} tokens privately + to ${args.destinationAddress}. Transaction Hash: ${confidentialTransferResponse.txHash}`; + } catch (error) { + return `Error depositing asset: ${error}`; + } +} + +/** + * Smart Confidential Transfer Action. + */ +export class SmartConfidentialTransferAction + implements AgentkitAction +{ + public name = "smart_confidential_transfer"; + public description = SMART_CONFIDENTIAL_TRANSFER_PROMPT; + public argsSchema = SmartConfidentialTransferInput; + public func = smartConfidentialTransfer; + public smartAccountRequired = true; +} diff --git a/agentkit-core/src/actions/depositTokenAction.ts b/agentkit-core/src/actions/depositTokenAction.ts new file mode 100644 index 0000000..9c4a763 --- /dev/null +++ b/agentkit-core/src/actions/depositTokenAction.ts @@ -0,0 +1,140 @@ +import { z } from "zod"; +import { ZeroXgaslessSmartAccount, Transaction } from "@0xgasless/smart-account"; +import { encodeFunctionData, parseUnits } from "viem"; +import { + TokenABI, + EERC20DepositContractABI, + depositContractMappings, + tokenMappings, +} from "../constants"; +import { sendTransaction } from "../services"; +import { AgentkitAction } from "../agentkit"; + +const SMART_DEPOSIT_PROMPT = ` +This tools allows you to perform gas token deposits on Avalanche C-Chain. + +It takes the following inputs: +- amount: The amount to deposit +- tokenTicker: The token symbol (currently only USDC is supported) + +USAGE GUIDANCE: +- Provide the amount to deposit in the input token's units +- Provide the token symbol (currently only "USDC" is supported) + +EXAMPLES: +- "Deposit 50 USDC tokens" +- "Deposit 100 usdc for confidential transfers" +- "Deposit 10 usdc" +- "deposit 1 usdc" + +Important notes: +- This action is only available on Avalanche C-Chain and only support USDC token deposits. +- The transaction will be submitted and the tool will wait for confirmation by default. +`; + +const AVALANCHE_CHAIN_ID = "43114"; +const DECIMALS = 6; // USDC has 6 decimals and we've enabled deposit for USDC only + +/** + * @param tokenTicker - The ticker symbol of the token (e.g., "USDC") + * @description fetching deposit contract address for a particular token + */ +const getDepositTokenContractAddress = (ticker: string): `0x${string}` => { + const tokenDepositContractAddress = depositContractMappings["43114"][ticker]; + return tokenDepositContractAddress as `0x${string}`; +}; + +/** + * @param ticker - The ticker symbol of the token (e.g., "USDC") + * @description fetching token address for a particular token + */ +const getTokenAddress = (ticker: string): `0x${string}` => { + const token = tokenMappings[AVALANCHE_CHAIN_ID]; + const tokenSymbols = Object.keys(token); + const tokenAddresses = Object.values(token); + const index = tokenSymbols.indexOf(ticker.toUpperCase()); + return tokenAddresses[index] as `0x${string}`; +}; + +/** + * Input schema for smart deposit action. + */ +export const SmartDepositInput = z + .object({ + amount: z.string().describe("The amount of tokens to transfer"), + tokenTicker: z.string().describe("The token ticker (currently only 'USDC' is supported)"), + }) + .strip() + .describe( + "Instructions for depositing tokens from a smart account to an deposit contract for confidential transfers", + ); + +/** + * Transfers assets using gasless transactions. + * + * @param wallet - The smart account to transfer from. + * @param args - The input arguments for the action. + * @returns A message containing the transfer details. + */ +export async function smartDeposit( + wallet: ZeroXgaslessSmartAccount, + args: z.infer, +): Promise { + try { + const smartAccountAddress = (await wallet.getAccountAddress()) as `0x${string}`; + const depositTokenContractAddress = getDepositTokenContractAddress( + args.tokenTicker.toUpperCase(), + ); + const tokenAddress = getTokenAddress(args.tokenTicker.toUpperCase()); + const approvalTxnData = encodeFunctionData({ + abi: TokenABI, + functionName: "approve", + args: [depositTokenContractAddress, parseUnits(args.amount, DECIMALS as number)], + }); + + const depositAndWrapTxnData = encodeFunctionData({ + abi: EERC20DepositContractABI, + functionName: "depositAndWrap", + args: [smartAccountAddress, parseUnits(args.amount, DECIMALS as number)], + }); + + let approvalTxn: Transaction = { + to: tokenAddress, + data: approvalTxnData, + value: 0n, + }; + + let depositAndWrapTxn: Transaction = { + to: depositTokenContractAddress, + data: depositAndWrapTxnData, + value: 0n, + }; + + const approvalResponse = await sendTransaction(wallet, approvalTxn); + const depositAndWrapResponse = await sendTransaction(wallet, depositAndWrapTxn); + + if (!approvalResponse || !approvalResponse.success) { + return `Transaction failed: ${approvalResponse?.error || "Unknown error"}`; + } + + if (!depositAndWrapResponse || !depositAndWrapResponse.success) { + return `Transaction failed: ${depositAndWrapResponse?.error || "Unknown error"}`; + } + + return `The transaction has been confirmed on the blockchain. Successfully deposited ${args.amount} tokens from contract ${tokenAddress} + } to ${depositTokenContractAddress}. Transaction Hash: ${depositAndWrapResponse.txHash}`; + } catch (error) { + return `Error depositing asset: ${error}`; + } +} + +/** + * Smart transfer action. + */ +export class SmartDepositAction implements AgentkitAction { + public name = "smart_deposit"; + public description = SMART_DEPOSIT_PROMPT; + public argsSchema = SmartDepositInput; + public func = smartDeposit; + public smartAccountRequired = true; +} diff --git a/agentkit-core/src/actions/getBalanceAction.ts b/agentkit-core/src/actions/getBalanceAction.ts index 181ca98..188992b 100644 --- a/agentkit-core/src/actions/getBalanceAction.ts +++ b/agentkit-core/src/actions/getBalanceAction.ts @@ -18,6 +18,7 @@ USAGE GUIDANCE: - If the user doesn't specify tokens, call the tool with no parameters to get ALL token balances - If the user mentions specific tokens by name (like "USDC" or "USDT"), use the tokenSymbols parameter - Only use tokenAddresses parameter if the user specifically provides contract addresses +- If the user asks for private or confidential balances do not use this tool Note: This action works on supported networks only (Base, Fantom, Moonbeam, Metis, Avalanche, BSC). `; diff --git a/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts b/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts new file mode 100644 index 0000000..9804665 --- /dev/null +++ b/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts @@ -0,0 +1,248 @@ +import { z } from "zod"; +import { BalancePayload, ZeroXgaslessSmartAccount } from "@0xgasless/smart-account"; +import { getWalletBalance } from "../services"; +import { AgentkitAction } from "../agentkit"; +import { tokenMappings, commonTokens } from "../constants"; +import { + BalanceParams, + TokenConfig, + BalanceChecker, + SUPPORTED_CHAINS, + SUPPORTED_TOKENS, +} from "petcrypt-js-lite"; + +const GET_CONFIDETIAL_BALANCE_PROMPT = ` +This tool gets the balance of the smart account that is already configured with the SDK. +No additional wallet setup or private key generation is needed. + +You can check balances in two ways: +1. By token ticker symbols (e.g., "ETH", "USDC", "USDT", "WETH", etc.) +2. By token contract addresses (e.g., "0x...") + +EXAMPLES: +- "Check my confidential balance" +- "Check my private balance" +- "Check my private balance for USDC" + +USAGE GUIDANCE: +- When a user asks to check his confidential balance, use this tool immediately without asking for confirmation +- If the user doesn't specify tokens, call the tool with USDC and get his confidential USDC balance. +- If the user mentions specific tokens by name (like "USDC" or "USDT"), prompt user that only USDC is supported for confidential transfer and by default use USDC as token symbol + +Note: This action works on supported networks only Avalanche. +`; + +export const RPC_URL = "https://1rpc.io/avax/c"; +export const AVALANCHE_CHAIN_ID = 43114; + +const getChainEnum = (chainId: number): SUPPORTED_CHAINS => { + switch (chainId) { + case 43114: // Avalanche C-Chain + return SUPPORTED_CHAINS.AVALANCHE; + default: + throw new Error(`Unsupported chain ID: ${chainId}`); + } +}; + +const getTokenEnum = (): SUPPORTED_TOKENS => { + return SUPPORTED_TOKENS.USDC; // Currently only USDC is supported for confidential transfers +}; + +const getConfidentialTokenBalance = async ( + smartAccount: `0x${string}`, +): Promise => { + const balanceChecker = new BalanceChecker(RPC_URL); + const tokenEnum = getTokenEnum(); + const chainEnum = getChainEnum(AVALANCHE_CHAIN_ID); + const userBalanceParams: BalanceParams = { + token: tokenEnum, + chain: chainEnum, + address: smartAccount, + }; + const userBalance = await balanceChecker.getEERC20Balance(userBalanceParams); + if (!userBalance) { + throw new Error("Failed to fetch user balance"); + } + const balancePayload: BalancePayload = { + address: smartAccount, + chainId: AVALANCHE_CHAIN_ID, + amount: BigInt(userBalance), + decimals: 6, // USDC has 6 decimals + formattedAmount: (Number(userBalance) / 10 ** 6).toString(), + }; + + return balancePayload; +}; + +export const GetConfidentialBalanceInput = z + .object({ + tokenAddresses: z + .array(z.string()) + .optional() + .describe("Optional list of token contract addresses to get balances for"), + tokenSymbols: z + .array(z.string()) + .optional() + .describe( + "Optional list of token symbols (e.g., 'USDC', 'USDT', 'WETH') to get balances for", + ), + }) + .strip() + .describe("Instructions for getting smart account balance"); + +/** + * Resolves token symbols to their contract addresses based on the current chain + * + * @param wallet - The smart account to get chain information from + * @param symbols - Array of token symbols to resolve + * @returns Array of token addresses + */ +async function resolveTokenSymbols( + wallet: ZeroXgaslessSmartAccount, + symbols: string[], +): Promise<`0x${string}`[]> { + const chainId = wallet.rpcProvider.chain?.id; + if (!chainId || !tokenMappings[chainId]) { + console.warn(`Chain ID ${chainId} not found in token mappings`); + return []; + } + + const chainTokens = tokenMappings[chainId]; + const resolvedAddresses: `0x${string}`[] = []; + + for (const symbol of symbols) { + const normalizedSymbol = symbol.toUpperCase(); + if (chainTokens[normalizedSymbol]) { + resolvedAddresses.push(chainTokens[normalizedSymbol]); + } else { + console.warn(`Token symbol ${normalizedSymbol} not found for chain ID ${chainId}`); + } + } + + return resolvedAddresses; +} + +/** + * Gets balance for the smart account. + * + * @param wallet - The smart account to get the balance for. + * @param args - The input arguments for the action. + * @returns A message containing the balance information. + */ +export async function getConfidentialBalance( + wallet: ZeroXgaslessSmartAccount, + args: z.infer, +): Promise { + try { + let tokenAddresses: `0x${string}`[] = []; + const smartAccount = await wallet.getAddress(); + const chainId = wallet.rpcProvider.chain?.id; + + // If no specific tokens requested, get all tokens from tokenMappings for the current chain + if ( + (!args.tokenAddresses || args.tokenAddresses.length === 0) && + (!args.tokenSymbols || args.tokenSymbols.length === 0) + ) { + if (chainId && tokenMappings[chainId]) { + // Get all token addresses for the current chain + tokenAddresses = [...tokenAddresses, ...Object.values(tokenMappings[chainId])]; + } else { + console.warn(`Chain ID ${chainId} not found in token mappings or is empty`); + } + } else { + // Process token addresses if provided + if (args.tokenAddresses && args.tokenAddresses.length > 0) { + tokenAddresses = args.tokenAddresses.map(addr => addr as `0x${string}`); + } + + // Process token symbols if provided + if (args.tokenSymbols && args.tokenSymbols.length > 0) { + const symbolAddresses = await resolveTokenSymbols(wallet, args.tokenSymbols); + tokenAddresses = [...tokenAddresses, ...symbolAddresses]; + } + } + + // Remove duplicates + tokenAddresses = [...new Set(tokenAddresses)]; + const confidentialTokenBalance = getConfidentialTokenBalance(smartAccount); + const balances: BalancePayload[] = []; + balances.push(await confidentialTokenBalance); + + if (!balances) { + return "Error getting balance: No balance information returned from the provider"; + } + + if (balances.length === 0) { + return "No balances found for the requested tokens"; + } + + // Format the balance response + const balanceStrings = balances + // Filter out zero balances unless explicitly requested specific tokens + .filter(balance => { + // If user requested specific tokens, show all balances including zeros + if ( + (args.tokenAddresses && args.tokenAddresses.length > 0) || + (args.tokenSymbols && args.tokenSymbols.length > 0) + ) { + return true; + } + // Otherwise, only show non-zero balances + return balance.formattedAmount !== "0" && balance.formattedAmount !== "0.0"; + }) + .map(balance => { + // Try to find a symbol for this address + const chainId = wallet.rpcProvider.chain?.id; + let displayName = balance.address; + + // Special case for native token (ETH, BNB, etc.) + if (balance.address.toLowerCase() === "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") { + // Use chain-specific native token name if available + if (chainId === 43114) { + displayName = "AVAX"; + } + } else if (chainId && tokenMappings[chainId]) { + const chainTokens = tokenMappings[chainId]; + // Find token symbol by address + for (const [symbol, address] of Object.entries(chainTokens)) { + if (address.toLowerCase() === balance.address.toLowerCase()) { + displayName = symbol; + break; + } + } + } + + return `${displayName}: ${balance.formattedAmount}`; + }); + + // Sort balances alphabetically by token name for better readability + balanceStrings.sort(); + + const responseTitle = + tokenAddresses.length > 0 && !args.tokenAddresses?.length && !args.tokenSymbols?.length + ? "All Token Balances:" + : "Balances:"; + + if (balanceStrings.length === 0) { + return `Smart Account: ${smartAccount}\n${responseTitle}\nNo non-zero balances found`; + } + + return `Smart Account: ${smartAccount}\n${responseTitle}\n${balanceStrings.join("\n")}`; + } catch (error) { + console.error("Balance fetch error:", error); + return `Error getting balance: ${error instanceof Error ? error.message : String(error)}`; + } +} + +/** + * Get wallet balance action. + */ +export class GetConfidentialBalanceAction + implements AgentkitAction +{ + public name = "get_confidential_balance"; + public description = GET_CONFIDETIAL_BALANCE_PROMPT; + public argsSchema = GetConfidentialBalanceInput; + public func = getConfidentialBalance; + public smartAccountRequired = true; +} diff --git a/agentkit-core/src/actions/index.ts b/agentkit-core/src/actions/index.ts index b116e5e..df80635 100644 --- a/agentkit-core/src/actions/index.ts +++ b/agentkit-core/src/actions/index.ts @@ -1,10 +1,14 @@ import { GetBalanceAction } from "./getBalanceAction"; import { SmartTransferAction } from "./smartTransferAction"; +import { SmartConfidentialTransferAction } from "./confidentialTransferAction"; import { GetTokenDetailsAction } from "./getTokenDetailsAction"; import { CheckTransactionAction } from "./checkTransactionAction"; -import { SmartSwapAction, SmartBridgeAction } from "./DebridgeAction"; +import { SmartDepositAction } from "./depositTokenAction"; import { AgentkitAction, ActionSchemaAny } from "../agentkit"; import { GetAddressAction } from "./getAddressAction"; +import { SmartWithdrawTokenAction } from "./withdrawTokenAction"; +import { GetConfidentialBalanceAction } from "./getConfidentialTransferBalanceAction"; +import { SmartSwapAction, SmartBridgeAction } from "./DebridgeAction"; import { CreateAndStoreKeyAction } from "./createAndStoreKeyAction"; import { SxtAction } from "./sxt"; @@ -15,7 +19,11 @@ export function getAllAgentkitActions(): AgentkitAction[] { new GetTokenDetailsAction(), new CheckTransactionAction(), new SmartTransferAction(), + new SmartConfidentialTransferAction(), new SmartSwapAction(), + new SmartDepositAction(), + new SmartWithdrawTokenAction(), + new GetConfidentialBalanceAction(), new SmartBridgeAction(), new CreateAndStoreKeyAction(), new SxtAction(), diff --git a/agentkit-core/src/actions/withdrawTokenAction.ts b/agentkit-core/src/actions/withdrawTokenAction.ts new file mode 100644 index 0000000..16f3f9d --- /dev/null +++ b/agentkit-core/src/actions/withdrawTokenAction.ts @@ -0,0 +1,152 @@ +import { z } from "zod"; +import { ZeroXgaslessSmartAccount, Transaction } from "@0xgasless/smart-account"; +import { parseUnits } from "viem"; +import { depositContractMappings, tokenMappings } from "../constants"; +import { sendTransaction } from "../services"; +import { AgentkitAction } from "../agentkit"; +import { + EncryptedToken, + TokenConfig, + SUPPORTED_CHAINS, + SUPPORTED_TOKENS, + PlaintextType, +} from "petcrypt-js-lite"; + +const SMART_WITHDRAW_TOKEN_PROMPT = ` +This tools allows you to perform withdrawal of your deposited token on Avalanche C-Chain. + +It takes the following inputs: +- amount: The amount to withdraw +- tokenTicker: The token symbol (currently only USDC is supported) +- destinationAddress: The address to which the withdrawal tokens will be transferred + +USAGE GUIDANCE: +- Provide the amount to withdraw in the input token's units +- Provide the token symbol (currently only "USDC" is supported) +- Provider the destination address to which the tokens will be transferred + +EXAMPLES: +- "Withdraw 50 USDC tokens to 0x1234567890abcdef1234567890abcdef12345678 privately" + +Important notes: +- This action is only available on Avalanche C-Chain and only support USDC token withdrawals. +- The transaction will be submitted and the tool will wait for confirmation by default. +`; + +const getChainEnum = (chainId: number): SUPPORTED_CHAINS => { + switch (chainId) { + case 43114: // Avalanche C-Chain + return SUPPORTED_CHAINS.AVALANCHE; + default: + throw new Error(`Unsupported chain ID: ${chainId}`); + } +}; + +const getTokenEnum = (): SUPPORTED_TOKENS => { + return SUPPORTED_TOKENS.USDC; // Currently only USDC is supported for confidential transfers +}; + +const AVALANCHE_CHAIN_ID = "43114"; +const DECIMALS = 6; // USDC has 6 decimals and we've enabled deposit for USDC only + +/** + * @param tokenTicker - The ticker symbol of the token (e.g., "USDC") + * @description fetching deposit contract address for a particular token + */ +const getDepositTokenContractAddress = (ticker: string): `0x${string}` => { + const tokenDepositContractAddress = depositContractMappings["43114"][ticker]; + return tokenDepositContractAddress as `0x${string}`; +}; + +/** + * @param ticker - The ticker symbol of the token (e.g., "USDC") + * @description fetching token address for a particular token + */ +const getTokenAddress = (ticker: string): `0x${string}` => { + const token = tokenMappings[AVALANCHE_CHAIN_ID]; + const tokenSymbols = Object.keys(token); + const tokenAddresses = Object.values(token); + const index = tokenSymbols.indexOf(ticker.toUpperCase()); + return tokenAddresses[index] as `0x${string}`; +}; + +/** + * Input schema for smart deposit action. + */ +export const SmartWithdrawalTokenInput = z + .object({ + amount: z.string().describe("The amount of tokens to transfer"), + tokenTicker: z.string().describe("The token ticker (currently only 'USDC' is supported)"), + destinationAddress: z.string().describe("The address to which the tokens will be transferred"), + }) + .strip() + .describe( + "Instructions for transfering tokens from a smart account to an destination address confidentially", + ); + +/** + * Transfers assets using gasless transactions. + * + * @param wallet - The smart account to transfer from. + * @param args - The input arguments for the action. + * @returns A message containing the transfer details. + */ +export async function smartWithdrawAction( + wallet: ZeroXgaslessSmartAccount, + args: z.infer, +): Promise { + console.log( + `Smart Withdrawal Action: ${args.amount} ${args.tokenTicker} to ${args.destinationAddress}`, + ); + try { + const tokenEnum = getTokenEnum(); + const chainEnum = getChainEnum(wallet.rpcProvider.chain?.id || 43114); // Default to Avalanche C-Chain if chainId is not set + const tokenConfig: TokenConfig = { + token: tokenEnum, + chains: chainEnum, + }; + const eTokenClient = new EncryptedToken(tokenConfig); + const withdrawTxn = await eTokenClient.getUnWrappingTxn( + parseUnits(args.amount, DECIMALS as number), + PlaintextType.uint64, + args.destinationAddress, + ); + let withdrawalApprovalTxn: Transaction = { + to: withdrawTxn[0].to as `0x${string}`, + data: withdrawTxn[0].data, + value: 0n, // No native currency value for token transfers + }; + + let withdrawalTokenTxn: Transaction = { + to: withdrawTxn[1].to as `0x${string}`, + data: withdrawTxn[1].data, + value: 0n, // No native currency value for token transfers + }; + const approvalResponse = await sendTransaction(wallet, withdrawalApprovalTxn); + const withdrawalTokenResponse = await sendTransaction(wallet, withdrawalTokenTxn); + + if (!approvalResponse || !approvalResponse.success) { + return `Approval transaction failed: ${approvalResponse?.error || "Unknown error"}`; + } + + if (!withdrawalTokenResponse || !withdrawalTokenResponse.success) { + return `Transaction failed: ${withdrawalTokenResponse?.error || "Unknown error"}`; + } + + return `The transaction has been confirmed on the blockchain. Successfully withdrawal ${args.amount} tokens + } to ${args.destinationAddress}. Transaction Hash: ${withdrawalTokenResponse.txHash}`; + } catch (error) { + return `Error depositing asset: ${error}`; + } +} + +/** + * Smart Token Withdraw Action. + */ +export class SmartWithdrawTokenAction implements AgentkitAction { + public name = "smart_token_withdrawal"; + public description = SMART_WITHDRAW_TOKEN_PROMPT; + public argsSchema = SmartWithdrawalTokenInput; + public func = smartWithdrawAction; + public smartAccountRequired = true; +} diff --git a/agentkit-core/src/constants.ts b/agentkit-core/src/constants.ts index e87b2e3..0f5ea69 100644 --- a/agentkit-core/src/constants.ts +++ b/agentkit-core/src/constants.ts @@ -43,6 +43,12 @@ export const tokenMappings: Record> = { 1088: {}, // Metis }; +export const eTokenMappings: Record> = { + 43114: { + USDC: "0x7cd958f1c47083d5911ad71fd32b856a8c77ab89", + }, +}; + // Common tokens that exist on most chains (for easier reference) export const commonTokens = ["ETH", "USDT", "USDC", "DAI", "WETH", "WBTC", "BUSD"]; @@ -371,3 +377,1250 @@ export const Permit2Abi = [ "function approve(address token, address spender, uint160 amount, uint48 expiration) external", "function allowance(address owner, address token, address spender) external view returns (uint160, uint48, uint48)", ] as const; + +export const depositContractMappings: Record> = { + 43114: { + USDC: "0x85ea5a1ae0ebbcbd015e078a08fa9cc0d00bdc93", + }, +}; + +export const EERC20DepositContractABI = [ + { + inputs: [ + { + internalType: "string", + name: "_tokenSymbol", + type: "string", + }, + { + internalType: "address", + name: "_underlyingToken", + type: "address", + }, + { + internalType: "address", + name: "_eERC20Token", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [], + name: "ReentrancyGuardReentrantCall", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "claimer", + type: "address", + }, + ], + name: "Claim", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "user", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Deposit", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "user", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "claimer", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "DepositAndWrap", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "user", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Withdraw", + type: "event", + }, + { + inputs: [], + name: "claimWrappedToken", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_to", + type: "address", + }, + { + internalType: "uint256", + name: "_amount", + type: "uint256", + }, + ], + name: "depositAndWrap", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "_amount", + type: "uint256", + }, + { + internalType: "einput", + name: "_encryptedAddress", + type: "bytes32", + }, + { + internalType: "bytes", + name: "_inputProof", + type: "bytes", + }, + ], + name: "depositToken", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "eERC20Token", + outputs: [ + { + internalType: "contract IEERC20", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "tokenSymbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "underlyingToken", + outputs: [ + { + internalType: "contract IERC20", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_to", + type: "address", + }, + { + internalType: "einput", + name: "_encryptedAmount", + type: "bytes32", + }, + { + internalType: "bytes", + name: "_inputProof", + type: "bytes", + }, + ], + name: "withdrawToken", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_to", + type: "address", + }, + { + internalType: "euint32", + name: "_amount", + type: "uint256", + }, + { + internalType: "bytes4", + name: "selector", + type: "bytes4", + }, + ], + name: "withdrawToken", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "_requestId", + type: "uint256", + }, + { + internalType: "uint32", + name: "_amount", + type: "uint32", + }, + ], + name: "withdrawTokenCallback", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +]; + +export const erc20Abi = [ + { + inputs: [], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "allowance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + ], + name: "ERC20InsufficientAllowance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + { + internalType: "uint256", + name: "balance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + ], + name: "ERC20InsufficientBalance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "approver", + type: "address", + }, + ], + name: "ERC20InvalidApprover", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "receiver", + type: "address", + }, + ], + name: "ERC20InvalidReceiver", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "ERC20InvalidSender", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "ERC20InvalidSpender", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "allowance", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "approve", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [ + { + internalType: "uint8", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, +]; + +export const eERC20Abi = [ + { + inputs: [ + { + internalType: "string", + name: "name", + type: "string", + }, + { + internalType: "string", + name: "symbol", + type: "string", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "OwnableInvalidOwner", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "OwnableUnauthorizedAccount", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: false, + internalType: "uint32", + name: "amount", + type: "uint32", + }, + ], + name: "Burn", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: false, + internalType: "uint32", + name: "amount", + type: "uint32", + }, + ], + name: "Mint", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferStarted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [], + name: "acceptOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "spender", + type: "address", + }, + ], + name: "allowance", + outputs: [ + { + internalType: "euint32", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "spender", + type: "address", + }, + { + internalType: "einput", + name: "encryptedAmount", + type: "bytes32", + }, + { + internalType: "bytes", + name: "inputProof", + type: "bytes", + }, + ], + name: "approve", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "wallet", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "euint32", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "euint32", + name: "burnAmount", + type: "uint256", + }, + ], + name: "burn", + outputs: [ + { + internalType: "euint32", + name: "", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [ + { + internalType: "uint8", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + name: "isTrusted", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint32", + name: "mintAmount", + type: "uint32", + }, + ], + name: "mint", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pendingOwner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_address", + type: "address", + }, + { + internalType: "bool", + name: "_isTrusted", + type: "bool", + }, + ], + name: "setTrusted", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [ + { + internalType: "uint32", + name: "", + type: "uint32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "einput", + name: "encryptedAmount", + type: "bytes32", + }, + { + internalType: "bytes", + name: "inputProof", + type: "bytes", + }, + ], + name: "transfer", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "euint32", + name: "amount", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "euint32", + name: "amount", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "einput", + name: "encryptedAmount", + type: "bytes32", + }, + { + internalType: "bytes", + name: "inputProof", + type: "bytes", + }, + ], + name: "transferFrom", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +]; + +export const anonTransferAbi = [ + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "transferId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "token", + type: "address", + }, + ], + name: "TransferCompleted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "transferId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "token", + type: "address", + }, + ], + name: "TransferInitiated", + type: "event", + }, + { + inputs: [ + { + internalType: "address", + name: "_token", + type: "address", + }, + { + internalType: "einput", + name: "_target", + type: "bytes32", + }, + { + internalType: "einput", + name: "_amount", + type: "bytes32", + }, + { + internalType: "bytes", + name: "inputProof", + type: "bytes", + }, + ], + name: "anonymousTransfer", + outputs: [ + { + internalType: "uint256", + name: "transferId", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "transferIndex", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + name: "transfers", + outputs: [ + { + internalType: "eaddress", + name: "to", + type: "uint256", + }, + { + internalType: "euint32", + name: "amount", + type: "uint256", + }, + { + internalType: "address", + name: "token", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "_transferIndex", + type: "uint256", + }, + ], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +]; diff --git a/agentkit-demo/index.ts b/agentkit-demo/index.ts index 3ec78c0..009caad 100644 --- a/agentkit-demo/index.ts +++ b/agentkit-demo/index.ts @@ -1,12 +1,22 @@ -import { Agentkit, AgentkitToolkit } from "@0xgasless/agentkit"; -// import { Agentkit, AgentkitToolkit } from "@0xgas/agentkit"; -import { HumanMessage } from "@langchain/core/messages"; -import { StructuredToolInterface } from "@langchain/core/tools"; -import { MemorySaver } from "@langchain/langgraph"; -import { createReactAgent } from "@langchain/langgraph/prebuilt"; -import { ChatOpenAI } from "@langchain/openai"; -import * as dotenv from "dotenv"; -import * as readline from "readline"; +// import { Agentkit, AgentkitToolkit } from "@0xgasless/agentkit"; +// // import { Agentkit, AgentkitToolkit } from "@0xgas/agentkit"; +// import { HumanMessage } from "@langchain/core/messages"; +// import { StructuredToolInterface } from "@langchain/core/tools"; +// import { MemorySaver } from "@langchain/langgraph"; +// import { createReactAgent } from "@langchain/langgraph/prebuilt"; +// import { ChatOpenAI } from "@langchain/openai"; +// import * as dotenv from "dotenv"; +// import * as readline from "readline"; + +const { Agentkit, AgentkitToolkit } = require("@0xgasless/agentkit"); +// const { Agentkit, AgentkitToolkit } = require("@0xgas/agentkit"); +const { HumanMessage } = require("@langchain/core/messages"); +const { StructuredToolInterface } = require("@langchain/core/tools"); +const { MemorySaver } = require("@langchain/langgraph"); +const { createReactAgent } = require("@langchain/langgraph/prebuilt"); +const { ChatOpenAI } = require("@langchain/openai"); +const dotenv = require("dotenv"); +const readline = require("readline"); dotenv.config(); diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000..9160a5f Binary files /dev/null and b/bun.lockb differ