From 4f3825258779cba63034bbe82058e40f9fca16d8 Mon Sep 17 00:00:00 2001 From: nlok5923 Date: Wed, 4 Jun 2025 18:29:34 +0530 Subject: [PATCH 1/7] feat: integrated smart deposits --- .../src/actions/confidentialTransferAction.ts | 0 .../src/actions/depositTokenAction.ts | 127 ++ .../src/actions/withdrawTokenAction.ts | 0 agentkit-core/src/constants.ts | 1253 +++++++++++++++++ agentkit-demo/bun.lockb | Bin 35747 -> 34916 bytes bun.lockb | Bin 189704 -> 195040 bytes 6 files changed, 1380 insertions(+) create mode 100644 agentkit-core/src/actions/confidentialTransferAction.ts create mode 100644 agentkit-core/src/actions/depositTokenAction.ts create mode 100644 agentkit-core/src/actions/withdrawTokenAction.ts diff --git a/agentkit-core/src/actions/confidentialTransferAction.ts b/agentkit-core/src/actions/confidentialTransferAction.ts new file mode 100644 index 0000000..e69de29 diff --git a/agentkit-core/src/actions/depositTokenAction.ts b/agentkit-core/src/actions/depositTokenAction.ts new file mode 100644 index 0000000..12b2050 --- /dev/null +++ b/agentkit-core/src/actions/depositTokenAction.ts @@ -0,0 +1,127 @@ +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 tool will deposit an ERC20 token from the wallet to deposit contract using gasless transactions. + +It takes the following inputs: +- amount: The amount to deposit +- tokenAddress: The token contract address (for now it only accepts USDC token address) + +Important notes: +- Deposit action is only available on Avalanche C-Chain and only support USDC token deposits +- Gasless transfers are only available on supported networks: Avalanche C-Chain, Metis chain, BASE, BNB chain, FANTOM, Moonbeam. +- 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 + +const getTokenTicker = (tokenAddress: string): string => { + const token = tokenMappings[AVALANCHE_CHAIN_ID]; + let tokenSymbols = Object.keys(token); + let tokenAddresses = Object.values(token); + let index = tokenAddresses.indexOf(tokenAddress as `0x${string}`); + return tokenSymbols[index];; +} + +/** + * @param tokenAddress + * @description fetching deposit contract address for a particular token + */ +const getDepositTokenContractAddress = (tokenAddress: string): `0x${string}` => { + let ticker = getTokenTicker(tokenAddress); + let tokenDepositContractAddress = depositContractMappings['43114'][ticker]; + return tokenDepositContractAddress as `0x${string}`; +} + +/** + * Input schema for smart deposit action. + */ +export const SmartDepositInput = z + .object({ + amount: z.string().describe("The amount of tokens to transfer"), + tokenAddress: z + .string() + .describe("The token contract address"), + }) + .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 { + let approvalTxn: Transaction, depositAndWrapTxn: Transaction; + const smartAccountAddress = (await wallet.getAccountAddress()) as `0x${string}`; + const depositTokenContractAddress = getDepositTokenContractAddress(args.tokenAddress); + 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)), + ], + }); + + approvalTxn = { + to: args.tokenAddress, + data: approvalTxnData, + value: 0n, + } + + depositAndWrapTxn = { + 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 ${args.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/withdrawTokenAction.ts b/agentkit-core/src/actions/withdrawTokenAction.ts new file mode 100644 index 0000000..e69de29 diff --git a/agentkit-core/src/constants.ts b/agentkit-core/src/constants.ts index e87b2e3..a4c4416 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: "0xecbe4f05955f232f4af30636845fedb9ba173abb", + } +} + // 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: "0xed7bf74200f4f1105a6cd606f66d4db500a906fb", + }, +} + +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", + }, +]; \ No newline at end of file diff --git a/agentkit-demo/bun.lockb b/agentkit-demo/bun.lockb index 8c0d27ede606930c44ae1631b9f4b531f50c84ea..0972ea8ce03c420b6a4e78ec38bf02f2777e5695 100755 GIT binary patch delta 3978 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 diff --git a/bun.lockb b/bun.lockb index b404291db2d4de5aa2bde82449b05499b537fdc0..4ae8ae6cbf5dd10a81079f1790a1f415ae0821c8 100755 GIT binary patch delta 43860 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 LBbWDWb>II3rND8> From 97ada5069a308b6883545e422c14a9bdc0c19ef2 Mon Sep 17 00:00:00 2001 From: nlok5923 Date: Sun, 8 Jun 2025 12:28:56 +0530 Subject: [PATCH 2/7] feat: Added getConfidentialBalance method --- CONTRIBUTING.md | 316 ------------------ agentkit-core/package.json | 3 +- .../src/actions/depositTokenAction.ts | 182 +++++----- .../getConfidentialTransferBalanceAction.ts | 235 +++++++++++++ agentkit-core/src/actions/index.ts | 2 + agentkit-core/src/constants.ts | 8 +- agentkit-demo/bun.lockb | Bin 34916 -> 0 bytes agentkit-demo/index.ts | 28 +- bun.lockb | Bin 195040 -> 189704 bytes 9 files changed, 360 insertions(+), 414 deletions(-) delete mode 100644 CONTRIBUTING.md create mode 100644 agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts delete mode 100755 agentkit-demo/bun.lockb 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 288290b..68defa8 100644 --- a/agentkit-core/package.json +++ b/agentkit-core/package.json @@ -35,7 +35,8 @@ "axios": "^1.7.9", "merkletreejs": "^0.4.1", "viem": "2", - "zod": "^3.23.8" + "zod": "^3.23.8", + "petcrypt-js-lite": "1.0.8" }, "devDependencies": { "@biomejs/biome": "1.9.4", diff --git a/agentkit-core/src/actions/depositTokenAction.ts b/agentkit-core/src/actions/depositTokenAction.ts index 12b2050..b2dd8fd 100644 --- a/agentkit-core/src/actions/depositTokenAction.ts +++ b/agentkit-core/src/actions/depositTokenAction.ts @@ -1,57 +1,73 @@ import { z } from "zod"; import { ZeroXgaslessSmartAccount, Transaction } from "@0xgasless/smart-account"; import { encodeFunctionData, parseUnits } from "viem"; -import { TokenABI, EERC20DepositContractABI, depositContractMappings, tokenMappings } from "../constants"; +import { + TokenABI, + EERC20DepositContractABI, + depositContractMappings, + tokenMappings, +} from "../constants"; import { sendTransaction } from "../services"; import { AgentkitAction } from "../agentkit"; const SMART_DEPOSIT_PROMPT = ` -This tool will deposit an ERC20 token from the wallet to deposit contract using gasless transactions. +This tools allows you to perform gas token deposits on Avalanche C-Chain. It takes the following inputs: - amount: The amount to deposit -- tokenAddress: The token contract address (for now it only accepts USDC token address) +- 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: -- Deposit action is only available on Avalanche C-Chain and only support USDC token deposits -- Gasless transfers are only available on supported networks: Avalanche C-Chain, Metis chain, BASE, BNB chain, FANTOM, Moonbeam. +- 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 -const getTokenTicker = (tokenAddress: string): string => { - const token = tokenMappings[AVALANCHE_CHAIN_ID]; - let tokenSymbols = Object.keys(token); - let tokenAddresses = Object.values(token); - let index = tokenAddresses.indexOf(tokenAddress as `0x${string}`); - return tokenSymbols[index];; -} - -/** - * @param tokenAddress +/** + * @param tokenTicker - The ticker symbol of the token (e.g., "USDC") * @description fetching deposit contract address for a particular token */ -const getDepositTokenContractAddress = (tokenAddress: string): `0x${string}` => { - let ticker = getTokenTicker(tokenAddress); - let tokenDepositContractAddress = depositContractMappings['43114'][ticker]; - return tokenDepositContractAddress as `0x${string}`; -} +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"), - tokenAddress: z - .string() - .describe("The token contract address"), - }) - .strip() - .describe("Instructions for depositing tokens from a smart account to an deposit contract for confidential transfers"); - + .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. @@ -61,67 +77,65 @@ export const SmartDepositInput = z * @returns A message containing the transfer details. */ export async function smartDeposit( - wallet: ZeroXgaslessSmartAccount, - args: z.infer, + wallet: ZeroXgaslessSmartAccount, + args: z.infer, ): Promise { - try { - let approvalTxn: Transaction, depositAndWrapTxn: Transaction; - const smartAccountAddress = (await wallet.getAccountAddress()) as `0x${string}`; - const depositTokenContractAddress = getDepositTokenContractAddress(args.tokenAddress); - 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)), - ], - }); - - approvalTxn = { - to: args.tokenAddress, - data: approvalTxnData, - value: 0n, - } - - depositAndWrapTxn = { - 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 ${args.tokenAddress} - } to ${depositTokenContractAddress}. Transaction Hash: ${depositAndWrapResponse.txHash}`; - } catch (error) { - return `Error depositing asset: ${error}`; + try { + let approvalTxn: Transaction, depositAndWrapTxn: Transaction; + 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)], + }); + + approvalTxn = { + to: tokenAddress, + data: approvalTxnData, + value: 0n, + }; + + depositAndWrapTxn = { + 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; + 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/getConfidentialTransferBalanceAction.ts b/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts new file mode 100644 index 0000000..64f7afa --- /dev/null +++ b/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts @@ -0,0 +1,235 @@ +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 three ways: +2. By token ticker symbols (e.g., "ETH", "USDC", "USDT", "WETH", etc.) +3. By token contract addresses (e.g., "0x...") + +USAGE GUIDANCE: +- When a user asks to check deposited amounts for confidential transfer or 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; + const chainEnum = getChainEnum(chainId || 43114); // Default to Avalanche C-Chain if chainId is not set + const tokenEnum = getTokenEnum(); // Currently only USDC is supported for confidential transfers + + // 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); + let 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 GetBalanceAction 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 3e476e5..1f52231 100644 --- a/agentkit-core/src/actions/index.ts +++ b/agentkit-core/src/actions/index.ts @@ -2,6 +2,7 @@ import { GetBalanceAction } from "./getBalanceAction"; import { SmartTransferAction } from "./smartTransferAction"; import { GetTokenDetailsAction } from "./getTokenDetailsAction"; import { CheckTransactionAction } from "./checkTransactionAction"; +import { SmartDepositAction } from "./depositTokenAction"; import { SmartSwapAction } from "./smartSwapAction"; import { AgentkitAction, ActionSchemaAny } from "../agentkit"; import { GetAddressAction } from "./getAddressAction"; @@ -14,6 +15,7 @@ export function getAllAgentkitActions(): AgentkitAction[] { new CheckTransactionAction(), new SmartTransferAction(), new SmartSwapAction(), + new SmartDepositAction(), ]; } diff --git a/agentkit-core/src/constants.ts b/agentkit-core/src/constants.ts index a4c4416..627f48e 100644 --- a/agentkit-core/src/constants.ts +++ b/agentkit-core/src/constants.ts @@ -46,8 +46,8 @@ export const tokenMappings: Record> = { export const eTokenMappings: Record> = { 43114: { USDC: "0xecbe4f05955f232f4af30636845fedb9ba173abb", - } -} + }, +}; // Common tokens that exist on most chains (for easier reference) export const commonTokens = ["ETH", "USDT", "USDC", "DAI", "WETH", "WBTC", "BUSD"]; @@ -382,7 +382,7 @@ export const depositContractMappings: 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 diff --git a/agentkit-demo/index.ts b/agentkit-demo/index.ts index 64a40af..f299584 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 index 4ae8ae6cbf5dd10a81079f1790a1f415ae0821c8..81e4b6fe17e33ba38cd20799965c4e68a385a379 100755 GIT binary patch delta 53217 zcmeFacUV+S_bu4n&`KjMB9c@j2?7d=ihw|a0Y!p{0WhFM36dlTDA-`etR)@{m@%M; zSKA^jPp(A+gioO zep%DD`(~?_)Ce%Gphkt~WE(Y7(29jt!Yqn(4ouBVii}7M7c@fwZRq!b2Eda*ec&EoQ{W9)YXa0!5ePJZV(_G=h11_9GKgV^ZZYktw0cQAwf6DUrXBDM5yxSRl{@t^-m9nW6D?pCB$R zA(=2WEjcU^_@t52v1`C)D0dX71>6Co`&I#)0~Y|vUTTU>Y-CERK=B9nA4O%h8bN+Xho;z!jth-afllRa1IeB_ zjKM>B&K@{G5nP7WQI7-xsevtkRM5VKKwu2?<{iBQ?@XXiMz^&Ajs;R+B7x+weGVpC8hB5)8q>c|-fBQz980dY%C5qQFMv`R;g z#2Va4o@=04RIo2{$mzF~B2+RY@Esz+AM0=nEupLkfNcjEi~ztKp->Lv}Z%9qMdk34TK-d!K>Sl$eC* z$mE#Rl$eCkaWPTRsp-j~NlBTAUt&UdB;7C_uA#X(ha8nR?BLNEwbH0q>7;bve@@s% z;HiT83A?qs(m_>tM-GO^*r3itK^|W&EQKbAKw#)X4rBg|PKg|c;P#S;$#5tW2Z|J6(Qu`m#XyR%EsP-Y@|>94o2iV05@X4*L- z;8>ucklqS^s3Iwlx+F4|su2icF?b0_$HYa_e)tP%Dj%xYQ*cnhQb>9~@J$5Xf*dTN z3IqKxNhxHuz*ayVpaHNhL^)kv@OT-h2fhqQ5n98eB|FwcFYIQ7azvcr@c@vTHy=(> zvr2hAG%SYBbePnM>EyWL4=^zUe{iWsDXsq+t@Q2#P>TCy5esHoSpUyjBC+)+rN)Fm ziBbA|8K{lYr(zb=wvl(i>OoBo&4@`<1Sw8w^ZOVjUjm&%i3J4nK1{F-I*o}r@yfn> z3MAiifaJqgbOiNbRALfZgT94M_80SfI?9nAk3osH%X8w9K_Qz0B*U{&0U0nEt8_%s zH)CQ_U%?@ox1ISQb;Ss33OzMBGBRd#roaq5-Dinb&^D$EBzsMO9U zDvVD{NevB;j%)(!`p{ET6x9fpqZg^ccA4l0tT8!Baf;a>I1YlQlLe3r3?HwY@4C>b zJ=sLWpFH1%1XWN3 zBtxBn=$o7kC`fw!Zgv|6Xco{u9tLN&NfRHL zh@j)l!?s1H;9XM54@fdneNE|KLHBDJxXtF$+>Ce z>JObF5;$Awxd)#g9-TNQCL%Q1WRB9Y6qc*0XY&nbaw@%XuF`xVunF`uKTscp?l^PCRtr$&Yy3|jX2iT`M$HnQ{I9$zhPC0*`) zVohV?G3=<8G0V_$WFcDm&AQfV916_eK607$jEmb0@29fYTAnP(z>lHKB);E?U zx}2``UwYumv)oQTx+BUxPK1YFYWF#r-H+Zc4XQZLRyEg`2lbyj+opQqsp&Hs#gt8X zIMLF3)$Xuo#S+b3Kib@zpR=N@Yu22C>Z~0P-)@d9T5)~l zp3|+he;2;d)K4t9qB(Jf4>#b$>J7urW{pV6^ZdQ5sBPA-xD$20!!t(h)jxIr>eb)R z-#Ukep6lFS(q&=z_+y2u`elDSnVq!!&cz$m+_u{-vrMXW`n?E{E^Pa3==gPqzUn;O z`f|W{72hFC_Kv*!(YF7pmU%5};;S}!o6hvw{paz+5s!zw-Z)e9_U%SVELz7gL|6Nz zkL3){W9FyU4{FycR#mfCp9)RaD#xCFL;QT_u*0^8%WQjgw!A)fvY_jemgi5e+ja8R z?mP251)~q2teQXe{@d3}mk#Q9!l&=kI1lS%d-sL3^mAAq(BxA0O$JZE~Kha{IPH^bH{Y%YK zSFK#LVpZV_v-lsQruFa|dDHc4NoUdL2e%!2B~J0m%gG5kl+&^J%)^Ug9&J9@Ex-1` zx*-}x5mw9RuHG@EF8j(5N3ZkmJ1=XQ@izYCvY=P~k_$sZ-u<#t(kw*w5dPq*L*&X||9Z)w497 zE?#I^;apLn^2Wh;o#0L8GWGO*=SH8pa`k2K=9;nlcd$-+oh-$#^1CGzY}L?OTB)c1 z=w_5oQHSGipI*Ira{1lM?Xt%GJiD#ul7fs-b+$@Z-*Z5dz;XABjPnvl#Jlf^O%Ghq zao8M--L6jcgK%zee2l8gGg zf0EwR_cI>Wr2UvOa^Vd_3{Ju5NMKWMw+`;?XcW!alc~sE-h+4M# zn?OUiRkLd^#?Sq})~~wH#twn^1~sp|WBKXfhZMb!dvEvev*GQ$CtU-(Zyq&AOURW5 z_cm+7Ew5xrE%fCV7pO|^I6ck|PntL&bjI>?&)@BDdDOV>T74(%nUMX)=&Z(7R+m=U z_3GR7UtxmUo`3WfRUGzS`+RQnh>TgOhqT|-&S_e`a`teWsOikxVe1Y@*OrE+Pt1-= zO!o~FF0bhGePz;E{i`qM^{0Ug|!ULm&)36xJ-}9P9hg@f?^o^U<6dn3LzH@KC zIN>$#O>5swWJ&s#&0MUfg`D$iIqT-FHCtvoTe>kveM`Bg+bl_**W;_pmYi=nHomM$ z*@CP`Jy)gAzuKn%l!Zp`ud0j}zHNTNw}i!$TBxr#vvMv9vKaA|P3tG~Ui)Q6o#6tn zgz!}?-SxDZW2+2|gXX<`TI`VX{^#=t{%2yU3`ds6Y`%3-`>?KS)YXWr>9K9=;)L6hOncwk zl4!Rp?tS=*cM-#eJa9SMTfg0u(3`6|4;XUeUEA@A&4%`_7FNGFoO-mrm)QK4#_VXz z86n+{A8B3DxOP&>p;1-Y9xIC`zP{_}e`cKSo$l5hCSH^kq@5p8W4JLxeelrDaSPk4 zZU{NnMl^KK`N+nq{j$sEx?I@#WA%?UA+qRs>h~R_@fjUER5*o2R`w{~kXIFH5o+0& z)o5B;{?AH2f0{foR8=e2y=`uSui z^~G*q#I3VdfatxVNX3))5^V5;8oZD6L$v177YEl_4TZTK0j)Mmdywp@_lrvEL>a1 zYU}1zItx!1YOnQ}VlvuUw|o%`X%ocew;td)tlhD0x$_5KuU{Ifvr62L_=~2^Ef0|! zCj7a1`T3!wg1KKG*}1JV&zh{&^2_?>%S8)E&u2A;#se;C_}(10`-9c2h(+5E-aGeb zdSj~0Dpy3--AyH&VqVwl{Y7}UA{kPZ|2)- z?e`tyR8QP~wDn+u|1*DiZ%J8geYx-pjmuP|iFNhk=I=OgH#BBtZH$}gH0?JmJo--e zHeLFJz8;@%%F5e>Fn6P92~M5@7o1DPY^=Y7^b|A)XaKwWA!akWgh)h&iv8_xJuOblO zHI$sDY`d9*V z9Wkr4mPtm6mHvwuNXZUpy!h&xX}p8Tq7jR=kx552;wysNV)n@j4K|Z# zfb35t|B{a#B^r$d0?+>-DPS|fdi@6*(nnF0>iy?_<4}nP9)NxRgQWW-z*4~fDN1ZH zSPC1S2m}Znd1a&~nTqqK9kFbzv4cbphhBGRD(DagNfxMj4 zMM+bfUU?1CPk=`EA&>6kHRXMk&?v&lLrGJdg6Tel*3v-|1dZ|g7d-l0E?axpd25OYhcL>RW{bbLDCwhZVG#2MLR>F@!q3l1<;i3B=4U= z>xq(zVIu0N#bWJck}-HdR0LfS-d)WFg5fBl2)0-g&s2S>fsz2Edi~{xz{_Y>V&*Ir z=_#wjc)-lzyG&XGHiBGIu=Vq4wZ1?w@*mc$JquYP(Ev#!fj7`W*=`R5WxG{jz~FDY zZ-X6-vKZL?9K^0IF+G@#rL!axDQdG~Oo+C(WY&H%tuG)4Qel|D6c7}_OgkD-+I?D~ zReTOI1WxDAv29l7iorGqdEJpGW_AeJ8EDk`Dhf@#wLs7nS|euH!9gm676MJ__*hG& zyGh8)*(VI{)-GzF~MD7{h)S7|sj>c;;F zndBi@8Wacu7L;a2tk_#7SzyEmfqm+L{)gtJD1vb#vN2|{J~GK{V}9*pcCHSR>(HqE zjoDah2WdMKfgtE_O$u+Ag#P1&mZg8Hf813;{?i)1$3@LdS*({#;%WMKyoNi7#+x$h zelp2=kcuThF|po3Q!EqcB?pP4nR3`Fybz5uW5u2_$sv%`K#bnb4x$er2gsx;Z3TjW zzs~US5}yN`!%7A?i~5P0EhatmfXP$pJyClKT+vSuMQ zh1m>r7HeAKHBJSWj8qtL(wj&n{6|gbSyd~%nxm*_hZU|mMn z35byYxXpNqM5Dd3Ta+QJ?_~zo7e$o|-D7CI{%U3&lo7!ag=H@k8Z8#hX(Wo5LhD7d zRQv!bXJ(V^qG}@$cqk_B7^M3CHM0Yn_g}50ElNSd9%Snv9tBOtY`Qy3wj(t_$z$UY zc4U=U+uS=UyB&*;m4kRHwC>ENgR}SuQeA14lhpAg8Y^Z?-%iSrjC~h-(jsWeaYg-m z85%!Uq0#D2BSDDu!$Hyq8ZCLsD3m}Op>zd{u>>~_goYVt=^)-r8m&U2wq00duuL+e zOZ^&eXXYsE!eU3tBtpzs8m&TVqr?>&t+@il+CCK;KiM%mjzFWKgsJc9AhNb+)-ai6 zuiS0~wB$$*@>(OsDE$SEZdajYSk$c>s~jqmOvidb^$8TsJ^>AFrRmh!LEIGUtS5^% zbruI8C1WL4&Z0#QtkP5_xd?)mFf47|9VDtq!W+`CgF8YaBZ~NlqoH{*8*^vLS)^p( zG2@LKB#kg2NJGW;4wBx`sB0Bb6m556#X&OBHz!tUEECywXVxY%Ng{lw^N2Fg`=RxQ zrl#n;-_U3}V`QL9WX>2?^(94_&dl0bCMg9&^@$WdRzV{lp`mBmAp$O}%F0F6w3Mk$oQT8c3B#s^+gwx&Hy(|AB#h{AAaXb|6;70@VN zh#q>R92&)0+2`v08n)XT8sC#94x(B8m~}6i=yX3;+*2m`^B*NwW1IXZvbE4)7Ds-n zVIUSznm0J)O>|U)LIXgtDoXA_`#Vv@IzBMMN<3UNkf8g80)YSpl}82f8nB9GTk;+$ zYJt*cOAO$DdTuPVza}MHp#9U2QgjVmLyuDr1VTfgX>8a!h&J|Tm7y}Ro*&L5w9tsN zk#b=rM$V#reyli5CixA5=8>Y0L~a9Etc6UHJ3#4*vWpKu`)7%8_ZJ8T;RfZJ!u(mK zn@s!`q>RN|I7_SsHk^Cop#9TFXQ0toQMRxNto&nk9<+b?72gi#aiC>+A9qh*pk;AoU7wob7z1~)eJ4$h)U0W8)< zCcX&5k;R+f5Ff~_U1bvAzy|Rbl?1Zl7@4FS<_m&B6CH>3Y0${Y#^}%%I5*=Y+eab{ zVwEv6vB^+0N3k1EMk-LT3ExACTvk==*DZ!A9vk|&s3PIU;(NIWhcWATndA+0@)Qfb zH5SF;7|Dvqhrr>i*bWT=LEWubV^8lp(G2onhW6{$$1{8&|ni>e|)#Z9xE2ZD9NEi~2~B+H;-52v{}4#()fd3a_OHyMpJoVGWy4^rq;BWLME zq-;=L4K|zOP^Wx+I03c;SdapAhVu9?GLB-ECNgnc6b2@X#{?DNIZEEaG-niT`|Vpyz+Of)ct6$9qPFl$qps1~HDOguOi;wX$|v1T$+^D(R#;5mj>n#m*+#?+5xI*IOvM#Bg}aK-^A4#R;?WRihM zksYifSd8|@u~>7N=t~?cHkV1-$NxR+V*)RS)<6l)6aN73u4su4n3hZt&^ic$<|p+I4IwAR@GM_gVI@7CCFMwUL*Yj3lN_&;j8hH~ z<(X+HH0lnl1bE$IIcc;hNNyvA1s6-or(hg3)Bkpbo1+>O+Uyl|OOEpz%wg-SO=p#p zWuieD%zBDUvNJ;&Y2=|lduJ-wM&%183!%|kf;_A&H=xl9hOH9^Zo~2QdnetO2yFoJ z6i0K>k?|~ckxV3+z={D86IkUUnYefYf}|MeFD9_qe3`@|OKAbeYb-GlS*#fDtN=-l zW4(`cRLiap7ERJ#&;}z5%|-p!p@k^D!Qp1mMCG%E;;5r_5*khfiaw-1p%-5iD}_WV z|GVzO#vo|!3L6v`CTFqJWs+wgyMlxVIHBt0C|^=Rr7;eYWN7xtYoZ9&0cbL4%JbY0 zXv$u)>*ydJnF}i{KHOQd5Gg8!>5kLSRcPIyA*48=HJhXylZs72CQdAl48SSVBg$&@Vw$M>++TVs?Y{WsM zLlVkiG#usg6vt5UH)wDjt3tQwilAUl#!jbsFWv?MYb%znmq<}-vEOuZkeJU*95K%KKvOn@PPHGQDdS0}JBvK!yiqh*6rIPc^JJn;c`P(Sr|&|DOL>_v(eXGM^-)Mx#(cc>x4&HfIg2;|Uef)xRSchf9py;vrCHjBkBmPvGH zE4Oo1_6hSf3Yw>4zLp|Io=X%1_zg4~=~yr@xI4~i*y1VBXsRiv;bmz5lx#Ft*pktzKtUHKTus^$Osui=DN&CPG&6lV*e-D4EJE{C|+R1@~v>w z6-d=0EQ*Vebc{_!eh&q!=wAhoXv-CeUVOpcd;vmo4Be=>2+5E)k3KwNuTfltl;2;e zDv)$PUMHkD;>4~fH<0HCqJ9N|oj`$u`3yn|Dt1N1jVU}&NS%TSM{oHMa1iRe^$;;+ zGlZ^&s0zIlLLIyVLf2nxtEX6-GOA+g)c`)(@@@%C;koThTeQWAtgQVhxooc z-w-vx58}%W=5YvLj*vn>l;?*jdAWcRD3AV68-_}xIt+CzVMr27AZAO{Ze z1sWo4^Cx)&r}+GasEhmx@O1wZzT8tDpYi1h$)T4(8Vi*|TBMZ;MMf20kdO*|0+Q#S zfz&m>fcPh7K}DhefmB3@n+Zi^fuQx>MvOw@;Cy37{r29w6d16EZq=Lb`PDr7T1d^dxAmxwYF%F1- zf&~1bNQ?!N;WQ$7q-mK8owk)3K+2lQ=gaF8gj8SwpYd-<6)fWO8zS-ao&mz8eE$Cq zsR7GS4vxwNE0G{#6_2ZV1BAq{0TQ(ie<%`LNcn$>TDbp^!VdbM5;V9@^M(nj;xj;^ z&hb1UweTX(Uj|aSE4+RUNOtZ4>H0UMuA%o)P^4ebeKh`G@i+V%QU$O18$R&m8X`GV zO@@G9`22rED)*hwC#13T3#eF(>i7&o@=%Do$<=5<19cNCA&JWohgV|k3@ zc|s~r@BN{Rkn{vzCnP9T^)C8W|Td7Y3JfQ`KVZ%E}g@%asr_+p+X zB%Lm@M?x1+uINZQK~mY~5OSM#9=Zrgr@fdA(6c06go<5Gq5U5{Q!4Bj;XblwEMPsC zwfygMr6L&reXdlDwf{a>(&WJGpao4#vqXVd_$d9~=gOXZNE#xoQS>}X7a=7*@Q3(@ z&y$o-`hTA*DMJ7DJV_BEp7Q_uT>0PU%KtuB{`a}^zt5HbeXgW^;oqMx>AB&*&y|Ys z{Oj{2ok9NXd6MoRp5pia{c~j`ZQ%dEKUcDS`%>LE1cnV?SK0CUm-i`S4{2+>*VZ^O z-DyOn+ii;rPgbe5jL6wrVeaD_IJv3Uuu7wQ&o3XebQRCN+o$8S=uro@*Jx(4`2G6w zKeDV>hr5QPY1xkIe!KQPU}?ax*g6fX^e&CpH?BF{of#g`m%q21 zdnR?-=hya~GgBf5l;>@jK4E*8@(thG>_{0Gx^02}7Qg*9C7ZfV*qSLk;kIj3zg9nt zUwoE^4ZL728SYRf+z5B-y`$Gj>MzyLSt};#jyt2j;ePqAD}#K}Klj{s`tYRFdOJ0? zY1$5N^UFNwh)q#f3xkVMi^|foTiBeeGw$8_*SWspDbBJGgSW0d*`)*eK7$L+Uwdjg zr`xD&s?5<&PkrNt*#=+c<}~j0a-L`Fw?`)LN&nJ3;Y6n&+`_(w4hw>7jBGDm^1k(F zXKZ%v0^4oPm%*KS?;5k1%YkghK`Fa**;^=KtIr2A$3s#kzThov!u&4;ve(ddLz6P$ z#XweYSjr+VdJ8q#c4(eQq^#(iw@{0HIv2=lpba_i?WbOXa zl`k?`;Zc32bIF^&KjH7Cy5NdI-d_LY7mHdA8y;%xF>KR}c~&npkH2}BGk(y7vzI@Y ze)T{6#yTs}WraA@p?gQYz=d0S9(;AK#W7j!qwm)o3t&lz=dBzdz0^^Esjk-4+EOya z``nn*J>Slp<+1tMQ@ye^EhPrKtL5kQa!y#ED~zk{>U?wD5{=RC?Jn#af3J7@8SeJ8 z&6*Y#o&RZOW%L-9Fe24*fc3APASqDQ5;uKfwN%Zq|J!bs)0>-Fu$jFde9ZsqJo~8G zeaqJ8x_szibhE{FbzyF0+c)R-S}p4ty{1de>QNiI4==L5VSJ!~UI!zO>Hn4KzYpp! z)jx5?I_viO?)?;)^5blL-hjDvZaWvbuU&Ld^6BxZZ1MftxvSq9HFh1!-Z)R`kSRIb z?Z>L{H6ka2*MmP#J{f6h0Yl_4*`@z6s=rj9pWboL^LG4|PEWGpj)s_jkmoLW@yxO1 z;TbdcTc?%=#m+8Y{>Vm%)OWOO=W*LPZL_^rb&HpdutW~iLv71? zt3cI?XJcP)>%1?ko87I7_se7Rt1gCFwzK_mz`04B+s#$GjfZs}dWkd0ZZzxjrrUx^ z9=i9N=;x_O{)7tr6ZcL$^=9^Sg<*jj8ODp3e=pV8HU-PG3!CpZn=;Juq|eL4=M8#v zQCm{{ezcZf*713bN;@RJcDK<>RJ~rAeMLGfAokVasSCag{dIE96O#{v2iLi>;1l{j zrt9A>JFeF~a^fWMbSJx3^E4*OiBYe@6+CTYnuPwu2>-%aGY!4`li$rJS#c&|73A;Fg*Q1K3#*@tPn^1e}*C zh>TNGE?WzPnSeX51;X;QloOkQFc)y+n}a9^v73l?0?t|+#EdgiHs`*#(26a1i1~U} z%BmiC3)?d%Xs@ANy6Y{pVFvdwU(ZR|3zY20>>gmgo|np}*53a)JRyC=h_t~+Rc-QS z<}GR4&)n`*xxIaS#I`n@>;p6_XT5Z4Y~{9l(c4(*we5S~!*|=cb(6P-qY{ z>5}u@Hhwuas;$l99jCdRi!VQu>UXWqoK>CIXEqhycvEU-MIhUFLCPLLvu8u^1hSxu zQg-N$x6pw}$^)6&B`J5x9073>aLp|ckTN1vh2BDE7WzJrMPHUOn@`@p^q!OYOErF+ zUCG#l_?LzU4W(1uE~y$`owa^RX7Dck7x`v$tM1-ylVoC9_&lTQ*Aa<(mK7zPJoNf; zN#9eu5=vYB`Xt!2s+LKw=*ugr;-^Hm7#e-ScgmT_u-z+98;|i^+t@Wwq@$O#<>2kT znUlAyey>&Bd4c@v$y=Oqxu$psgH9bz1 zd9+w{y=>?$N!8+0nf8~Wy50RW(sfYpn6Talj<=5-8Y~~PHnl9P%jn%2x2-00?dY?3 zg+}z^R-upjc{MQX-q5ghTlWoLqs@!fExdE^iSy0$du!A7xR0~maq!}pmchQ2zfP?Y zt&c9V?2`O-VH5AX^W$3o9;LeIpv4|9n}G%f1Kk4}*zG~D9@k&0E-Q^gHY|Mc;p3E~ z(9bPDhLjeHKAFACue!3C?K^j|w^7p>5$~+dh{tiXG+g{qd?U``ks-R^G(x&_h+gIH!i*W^TwZ7cRI2yr9Fo(TGp{>{9@bJ+=PwG zdX08UDDAtx&)}aod!_d~@mjmA_I61m!P>hLNha^_HU`b)} zUUBTeI@>BvMP+4InKJ|jgUZ%PS4&y;b$w=7>n-fZVrnt3 zZ(s&s6!ZTDp{PnV&8#%MNww{%+>9y7PEYP^SaxOJk~A~lw9>+j@p33;4{qqoHKYB$K9+fHNt>@5az!`vhE06Q zfkib-RTi3bDsJIWIo>dAP14z(Ca&##>>s}9o>((;?zhFyuLNc93cbDSUGtrLwj8sanGvwx@ONGyo~tgNwLb7@P5Ge*#~-;YX!P`2o#)q)XH8b6Ht^1m+~P0Q zj`y`o_Ki3S}59y~Pe%UM0# z+QPX}vvn&&{Nlw;YPT2bGS^%B?9?-FUwW%p{iPZa?fz(A>V%qZI|ppIRKERc)jgZM z{coOR#lCtPaA)qMEW1gmejj5ycb456c2>8r(Jia2RTIi$w*-xAA91zI<}@Q#1*=28 zc?$=z)!(r0-NxzbyEi_i;r|`$-W{C2pan8v4c5JKsa(rtdUN0W))QWQJrW-A+q3nz zQo}r_cb>ym4EEo*;m`={;lE|WH7u^UoXE{GU%g_~&t{!duG?v-cf2kuQeytz5#c4f}1fg4h1JlVcPt=gbi zTWw}@*PqTc9eyoI(|>sPbZOAH?Z$hJ6@9Noly!UX!McHW!y9_n z;p5%Ui>I`+Xr4aGt*Pgw>GP^@Pl(W7xNSfho4HZz^ntArho;_XKiy!lrB3Su_YLQi zc1o+-wK~RP;;duU&M8eVYqH?G`t0i$Z{OgCX047-DsES$${Cb?IB?!e#n`9$n6%q# zRUdV&buHJmo0G94#AA%V+PLV0t4}uDc0zOY_?cA$M)WqHu621n&s;xy z3r8`lxAR3z;EnC5U(dOY{bqT~);Zq>N^*6PICI7NRw zz2?Xt$*swfeJ{dCl&aQteV_4u@Z&l9Z8!ajsJav5xu3;X=(9Q1-okKZRUODI?_=+; z^Y)EwSjTP2*MTd7M)uhon$uXnczE8O`7dTXx_$NDxAm7?lN&r1^D1Z{Ng*-mDt@MR&*aoRR7BS(mpjSW}*nZZ^>` z+bVzOBw>r~;ZN?~%lfn0B;>;6v}EhZ###HDv>CBIJm-MMn9*&XhOB(r=mc|ptk0DQ zQOQ{DhY+>YJeG37BIqgHCK2?FPo(lw-$bex6EntN>zt&^1w^{0EScvd{Ty*dxB5v> ztw7yJ_E8I7IXtl$*eCSJulv?Z*n?j$ht5yEpq5**ZSUb3t&YLr`gxGn(D@6ewYyHA zxz@5z`i)%{9d=%@URT{Xe8rn-zAEpo`1Fr>-mOoJj`_Q zxe<15?@gU{yiohYe4pyGv=83GbheMqD$k@W4d<~;rgb-vl|j38&s#Ww9s7WD%5y0* z|L85uX6HWQsQ5z4g5P-y=?9i zXyz}xh11#C7wEg!r~z6Y`|%ik_eRPL;ma&esDi+~ek0{xs3DMZI6Db-U!|1O!C_Q5 zkK3mS-Se%KGi(NZ0T&92LRWh) zd*_h9!;R@e?-Shp|5014x`Ob#iXw0K2dhY zCn;Cd1o~QTD7kN0jp|gO7jY6*=;hE2#lpT~dKq8?m#YSD#%G*(4|oeVF}s6k{}(B9 zeeEsW%<^8N`OvDMm9RHBDHnW|vN}Yulsnf5H+p`PayE@&d^?xfSU5;b4;VYR7_l%= zxRblq7$r7-mvZ(Lz1`d~&@8A%%9%HUzLy(I7Sw)7<-WfbZoTqjMWT`W{QIiTi&jW) zIrZFShb~iU=@%+aE?G*>tZE2i)q~Wn> zU&CS9J6L?8^73;Pqc2B0$LO4WEKVI5^kdPn%D~paUTXOX9R^Cqt1gZFV=&iORJPpl zXKL}*X-&TlYcc)F{j!46!`DX^u#zA8Ec>Ik=zxHWr89GMEf$hj-oiud?kn`fPxQ0} zj?_m4T+4RIJ`2L$3dAu1XKD!|`vRat{LCE&WZ2T=~fm54I} zZl*Pe8NV@H$i_JVcb#lF{=u_OI}jJ}tV6ZD{)5*H-g*l!vDI$_^9%4QgZQ1d=!$?_ z2!oubP>Atkg9u+^*Iov4HKdDeasLfGO?5ztjUq609l+cYa06|@1gU`WCFTwuux!An zse<|19#-zM1#bemGU&|rrnj(yEx8#eywBde2^2lR`_I~*hs$U7X9R{#ALjp#pC73q? zF03UOM|CiDx?tX-Mk@0fjPG|h?a0-$Z*%XCP3KCyQe^w=KJ~jDTHY^txM|3_{bznT z)uv4RDIQH#FwP5;3C%h+D0(??^E5>n~NkfQc{M zr>>7^adGkPTN_)Q{pyoYp#6K5L!If4c0tvRBnQ&^w$Li=_+`1ug39YX((lc0EneK& zZpzcxmYz3{t@QBZY;=VB+yhi3Y9eFlob|1bvPbf8-U?|i2VCA-CXRYPV>88V5 zPdRVD;@QQQt+upM*W36je#!EzjER>{4q7iVc+<;eYya^%YM0vG_-<$SZSLIg#0N*( zZ)vrHE7V5=J&fV64tKW={0%Zd16++j=y6s=sI^23^RIgg4Y;9gp_f7D4z)#rR-D8f zM06_<@$~R*C}dBsW5%?m-nxZXIE1YB7P^;oj~jS_L&z#`1aKLK(CcpE^$j8OLcV1i z=(}&@hWMhHF5UC=O&(s*(^?ETq;qtE!Q z%@Vv@pM1oxZS?({5mkAk2Zc$c>Ww-b9;e&fqvupX`>$n>j&j*XXzFgP6+$ac*b$C9 z8pH9(jv(4|+lhEh#HmgoY&b1D5CtY6((FKV#4v*2Ss z6;}%lS5#HY=+oSttIcbR zR!rMop`O3L9~W#P)R#LD}B9<3H{QXA?r|7gqH@m%S{+$U98gFuw&dS$* zueo<-`lEN6tLCR`RnHO0rvKioanI$mbq|9xt!rMmzmLeOE1lqbWv6^_-t~Z~!Mn$* zJ?5nC;2sN3j?xXOeY9%W$Kj?Ib#GWp7Jq2n`tgBrtu`Ee_c}=aazsd2c-xH7xvK>| zkKFg@@WiV}b--?q@BT$kwzSC9-PXW8w}$T3`lpI_JZ*blC;x3t#)hI3Ll)a?oH?rL zJFijNuZJJYk1-teAtO30!(i>HXa0ASr*>MKen!?9UwF!0|5(?`MtksU?hv^*`NzxW zK`qAoxv1_M66lxWv*=!zHMxTEvm72chYq%uA3Xl-(d4A}!rSK^BeR{g>QepGYgbej zG?Vvft|lJQRJ^o-dp#Pur=9CD>T|k0C+n(c@dnPXa<**ZfUh=Ffl1-W9Oe1k9-d;?83!cVkDP1Vzukl(6CwH^{h@y zIXtu`rr(^qVGsxE|{gBhF@t*zWK2=^#zZ}(xIQsrZelw>cHM4#( zKfCPgu-kFuM!Ch8%7p{c{ANwDSwBy8%UbPWHQ5cCO>e-dzf^1eMup$F*6p!|p_ZqA z*~~8$ncH7BHtITm=hg69GgaSXC5smw@Cr#WNQ%h!SJ_)Tep(05Iqm0WS1-7vJH$U` z@wFY?CAh~t4te|5zoCb0tCr6(UOv@t_m7Jw?yUG`7~D3YYQv?8A76fVT>QOr-OtiC z-p~9huG>DC+bREGc>bmXydwbF}-6h?Krb*#{QA>KUDY~Uy*-#PuHMV9~V6e`<3h0hTT$|`Q7M{d1=Aw zc9SB9mw5XXUHuqjKkHqWzK0Rf`UPpIkPSN)z?G5N;^W%x-(Ma)u~2wtM^x1~vp|{J zx-Gke?#DkI`q2GVP@}V@%MKpjJH~qYqDwjj_%(IOM1)@^pnl8=>tWO7sMx%cKQ9^d_G)`>xLJj6}#zzz* zWHZm;yw(klR-N${jS;f$XVI;sOON6Cmy2ihi#mfaD41@8Jnm&C?!wZ*4gBR+4A&h z7q)*jzN@D?a=VX3aIcn)`(7A5Y2tA~-T6N^S=UoX#~Bnnr4PZ?2PUOqz()oYPiy5e zS)=2c}HixuYasfA;koUz47`{BcwN=aaBU8PDnE`+9%VITIPo zsyQRvQ)Q?plenwASQ6RZXlvvK)fI#o3nEVq3;SJ-yIXa{{3w*D^TtB>-XY^ zJ^Fk)xN)WW){S1*4-D6yF?^Pn+2aKHJxk}JoqDS6tA9E))>>R`QeMb~PU-00X|Jx{ z6V9PYqLGf-owM8_S2X!+4^))P_2`L;GGwTz3Ka<_b3Z5smTn+|dxMzDEeQfqPDEW0 zi0NFvp&(|sgD4paB9Hq)gkul7Wf+KA+@@h5UK1f54q^^BbU28Do(ODO=x4){#Tz}& z{;KNz<@MXuC$ue>j9X%Ta!pX0Y2M}|MKX(LNzrNVMi~vaeIL?l+u)#q((C8c+!wiZ z9Cmg>8@;y;0y~eBjDT6sUZ`g``MQ7;dVr`QBGLl{sy*?WT)oQGsxJL7+-J4ODY%I2C^-vA!Jg-C7GfSgF z-n@GKiRp@ZMbiVgH2EC{d!n>h_mq#>ibMy*CM;larM%^ zJNr(1xzb_Fz$b<;Qm?;u3;h!nae1Z9i}tc6x&3=zb-L$1bc|K!HkrQME%z?>98w0D zf4kLNBiO7#4{qib1j60dK5+Ld`Cr0~r5F_Wf_UKtqLf?W3&OKMh&p=lZadenKZqJ4 zO8SG?$^9T=qaTQ1KM=dQO@1JP27r(b5PEal1_%#vX#spYc+H(9BAcm|>pXV$7#axwWH* zzT=5&&$rH)I&VV6k81AH5DcbMBT&&9PAeD{%?Ln6X~C%IT*HcDpH#QYG43M!klV5G zhLrJ!sp}V=8GOFQqLPmucedES8vkk64pm3L=`GjiuIIXp{&B{3on)fP>s=OB-3(Im zd-vDjYy#1%+n?|0@4DYdr+<@h&y?896XNznyniTfuDxr|2m`YXtyB8<+O{swebkAb zo$j9Ne!8cLo9Kz<_3IzC4^Q!m%9X^@TjA>$ybIhha`$y0+%+Ew|1WW4M}jB_0&$Co zE1bzF5S~M^Af$i(+U3izWEF>0!w&7vKg-k(Jbio9{Ev&4A6swy!1QF{c)d@K27P)S zifV4~b=s9POM_>`&yL*O zp>bBe=wPbx1+H)yI^+fH3U6_Cp{OWmIQ&1fr!>9os`##N3;box&ldZ;yy$*-_~oJJ zc6-;kS)EoBm1e82H5vCor((U!mD4AWK05zow)q}mQx4du*@`RkC z=K5b8sl!_-6yFFnPeI4>KR9;HIO zR&0umqNTcBls}$<@9T)^xYu}!P*ssH{lC=uSz&HP59M!kYy>tVbJG>Y)$4x z2$h2}6!kw)@?$1`lZI?O;(YRi?!rafoIK%PMb!6>m?_kC`I{_kqwaVc!wXlzJ?`jh zp$nJzPAG=m-+z=BWgSKdDzpj%kS@}x*(CKJOFYVRRK$@lcbvbEUj2SRg>jt#M{i>z zq0hR~b(Swjp9&jA1idwYR#f~`d^j}(NY{CuqmMa;DHws^0?*M&J)Gw*@*Ku6eMz$7 zy2NuB=z?gTyUcU+k&YOiy8=#exTE)1)PHXHDqpZExHP_X*LaTJKA6FC*LjZK0_Dwf zwB%7k>0`bIeLzAK8)r{fPG+o}|^IJs+-eo}+iM+49_7o}+i5 zIq=*)o})L9H3moFr4Pm9pW=OA629Dhp2KVwXel_v{{c_Z`>m*d=z7R=^j0YfF?GWu zo}=#VIR%Kqz!QClY7^ znU4hZ*9)FAMS3}9;-ZgSP|^%y!gH^9t}VDizQwP3&K%qdaMaarc+LW8dHv_f@tpt) zgY7`}N8eGuz6D2iEFtvb5xqr`z9Ins1XhqD2wm^_a@I)q#SPS5ANg|ak!}f&x{JP6 zfbQ)82|xmG$&(AJdC~?Xc}sosndfYgrq)x}eBrr{NK^MvH+z_<~)*^?=Y-%X9WfZ-7wCfAU;6q#cl^%6{>j z1JWIkri;EXfs$uwgyK3%0|A%1OInxCGUKks+|YMIXZcnHs1&jtvJ|mLd)+6 zR7Hyhtzz_URhkJj@@WyG(N4=RO-ou{H>q&_-wRvH>9fv5abG@gF@%E@K$bw3LY6}o zK}JA=AtNE9AR!P2p^u2CLTITU2T6y}5}yef4^f3}FCZ=P_}slf262P9L$Jil6(9Du zgJKKm2(f@zLd+rbg$Ff|ACOwePY8Xf!W&2>AOfC+x)yxe)s16&2{J5ZVKpLTKG@0nvfb`a#p1 zrt?_{?Ygup-h|M`Maw*G?GsQrsuJWtra-1bra}7B_Sqjo%XdD6gA_n$nJ$E^fUJb9 zg6KhvAjS|{vd2JtVZ;kUui4NisA$1q7eW}MIm**l1r$Q)qyC`~c^LlW zL1sdxLuNp7A(J4JAz6@Y$V7-64AMtXJR$uceIfMK3G{so^c@T>Aa$tdH{=gQ2%+z) z&_u;Yaqlt6amWmCc@P)+8X5XO4|hlpNGQlK2z?rE7-Tqv!wpLz%OQo36_AyXwUBiX z+CyY0*8|cE;sNOg@r5M7W+21_X+uaG$ZzO>AhcgSrtNbl6922V>i~=D=-SI*!-6ys z5fQslcY&o_v3JDYl?4`9U3PI7q*%aiG%D6(uQ6(3uuC*{lURZpqp^1rV>FiN_r(%5 z|9fr`Ka?;3^FPne!^_+|=giERGiT16nS0qifl9swjsVYrDZo_VV_+IE9ry&80n7wu z0lC0zU=A=BmQFjv;U zdSC9nLrjW3TOiGhi36-NDKpVfB`^Xpgiye>evW;3FHC1 zZutXafYE>%Jgs?B1mLC{7@~m`WZHo)z;#G@1Gov?27U(40UVxvgEAad9RN5&;)sZY zo#mkM|N2Yx}@f`zuf| z0x2Qo5A)~=@cn0~n3s07+=tRI@C5=N0j;JZ5I? zaB#x$A-iynjL^0Q+0q<$N6IeU34kn8ekr6Sff9gvU0TU2gOry6XP^SW>o2dvWfkz! z;KswkYX+|!yoT^v!fOf}B#&VOfM)}bZ5+ToVr$-o>v~B20A)|~cYWmXHFp5n8ZZ3e zNP_cutzudYq}2gGpe9h8ePu0N)B)-O^#DDXNx(#4GB5?03aDkj!nHaJxU*_K zFzjr}YS$n$2ABb`YCi!M0tCzlSZyg&W`@eI1pXv}c<9dri*p753kPmPrJS^`{(S5kzqtNyuJq{cLjsk}P z7MdG92pjiZ&$xKEm$z`wlCz|@fp>d*5BJRb5_q@A zf8hQR&;)>0zjf6QaQ!=QAGia&+k2@l9)GnWR?DxzUEnw1U7?s+<>QJT0<3D*m`Zz$ zYi?*az=Ehl^e3Pk?Ne{2A~k@NeKb@B-k%Y+yyTqmD0^`vtfO@L2Pj ztM;6QP<#3}u3rPM09AWxN5GdYspSobJl^WKIH0n3)t(0$Z%ViqE=VUJk4gXEk#pr9gkT*CUa~b*V$Bc8nW$1}}R~-Y=Htu$*@-YQx-<=|CmqamY3U*WAl~ zzyQDlc^szm7K`&#FwGNrO_8en198oDF#lCta~sug%|e9(+@b6$$lyrC7dNaj)&xtb z7VuUIsA^_jAD}A0fog4_4a(F&>IYN@e1S{ItA(^CP)E6Eo)CqX=?M9=rJ$505DWwXdO!_eFX8$$Pz_~%KaOx1~4AD4o2RT^5!%H*LI{fUExQZ% zs7%sO7Sc>$48Z%pu|N)x2P^|dfwvZri|biD{*!R=32+OUT=8^Ve+*0k*kUIGyl(Si zGZoj&GY#oXUzvunWisvbW*S zCeA>`ybf%}HA}h$*b3|fb^zM}uIwvd9{Bbm-2;3B90Cpl1;F>fF@RNl6xa^l?~on= zjsuf$&mGu?^ppeEFYeh1fEl*}CviOy=>?>$>S{>O13v+0fiu95z!#vMLwXSi!1WJ* z-~vCo?v&*y>Q?7#c3SQj{&L%1Z}``o>}bDIRgqHxIZfzmM^Q!F5x3>|cEg0Vk*--w z$~X+sN9aOyfx&|niu#@AWgL2uLkVGZNTLxXgm*}q#Rd+|k_J-?HdninDo{`tq>F&< z8IsLR34U3AZ{PV_hDel9T_CSMRKA?>@+k>HxzSfI4sDOg^w54=KD@fL-|)gR@7IRPB6QWEcOKUdS9eCx#`3~TUpxmNX_rTX zb#K0^_`1QZ9O2M_HKL(te049aC?{%&jgEAvoY0G%j`U|a(IvZEN$I#Cr~m$kC6``% zP#-etCE+!ng2FxS+x=|U!B39el%z+;FyTtcWv16%yyDcVyUR;B=rMG`XlNxUZYUGe zLer$`scY*BDO*9|+AdaXdg{=Pk|z{OPZT-;5*D5u?~Z*c8^xJ9g@sOo;sT1>Z#_1& z9ZmfTDK|l31Dl>zV&U0#LDk-&l%dTP(7}6U=wX2H5+$6-ubS{6H)rANQ^84=;@jME zvs(1I>x@3J0YL3lov4em(AMA))zkqSesk1seU{jQ*-&&&l;bSChIR&-O=hKn~_=4i&T#-adUH6?b#hu&^CR zUS$2Pl!OheEK8!b(EIcQnK}A&|31p#vi%4+LQpq2;>uBUYmq=te1*5eU~=#gReTOZ z43>mKy52Y%USTP?1JMUvxaL%O3h)qKp;thz4305wP4zqT&1VW*d<0ERV;g`Z94N*lqi-D2ncfq1ngIRKU$n#E`LIPS&R1 z-Rr*iYvC|9RHx?=cZ30Q2c!HCt*&zXum{S@K11W|La*F~UVjc8ti;$6wVOqjs~D~b z2FFtejqYucvDU#;jI{|mssseDSdd$5-f3}L1@{hc;ixKQ0k@ObVn)vf$EofqqJNec^Me@}3 z5}lps2Mn;PiMJ|P?M_iOk)P*Ik#&%&T~S5<+MQN%J;&V_Fq0J2xx^99-tiVFJhg^=Ua{swzjU@Fn4m5Q`!o-li4KI;tR$U; z=9F#Fe~{}5EiX`ESQ2$1nvS5+P}=!11(8fzuGg0eodz)=Gn{RT|v z^OeI6o*qi=n=6q^UDSRP9GERRy6$1ezHJ?KtdPUiQ?C79{T>HbW*w_>Ec>xi_Ik*_9=~v{{iu+#$&)sstj{%Y)JEC8(-!%T{%N<| zZ>d)p*c;#=&-xhpPW45wPomLc&$Ps8V!XSBE$vh8gm7pKZ@{w)gT1+>@Ms(cg|%1m zDziJmWArVUV{MD7?(Hzh!RQ;9$P2L5UJunKsuG9=&)NM}UicwD%vnN$4>1+;11To3Ia4Eyy!qfrFRoxy4Y3b-2cM3cKMGh zcB*v-YUUyuVJ{anCob#YvXx_m!(`;Jc2^*UdFI@2VlW)jM>(NPActe20o$rjF531w z01gafPV}Qy>joShJxJmR)CJLjM#4ul@TP0v@-8Z&i$k!typ~dABjFugoaTcx%i-JE zy$`wgSQoX@`{P2XcOx6Ie$JifEXS_B7v&dH6#Eg1ZB)Z#DRyiFsq04~L}m5+?`EVJ z3ye*#`M;QipD$hUg3D3V5?Xv0iZkU9jnb)7Ea_Tb@@s(l_V`j{7ld-%8i;CQXmzq6 zGjt?Oi~Y(ASL5(E!6(==V~v5|(4_mx7J2i{iM;y36&6YqJzLbs>a^#b3M2Hvn)0wi zuBOhnpY^O)by$f)H5V`ayD}=*VLS-M^-5p-G@>!}MO9Ixqa`7iG8WK-UeyUkFI3YX zJ_WXwGiFcEoF)gST$SWi-AarW)8!vIME}~92TopLxWqr*7gHlU%3^Bx|0wa{I^pC3 zRVhBq@xRawY$K?co)p#1huipPDcmMR?9lt9|YL8r2oiG_i*l6OzC!|^N;u2J?=J_8X2@fxyh)AN5(%;f`U zJ5&zC6ZNDEMqHH%4lHXqj=zO<{Z#W?COCM=Al(Niq!hyEq6|Bqbt#oD|LHu&0c8+; z^V<1ZPnIFj>Ag@4Ua24|6^6|nb{~zyM3*Yh5InIa=k{6W&|$5^9x1@)olW8Li7KFk z=ur5B4|*lciZG2Lx~LRF%b7FLY>mavRFlwm#zXJ^QEed(rWbbsX9=6pNuieLR+3JJ zphWSzN zRKpukTu|oQ@9*sxJG9FPl|rLKu$2hry0?Z1Z~fMAxd#7=Wn!z(-gXasIErA&_bQZq zJxqtin=`pms{y(&Dj$Rz^l`$iwzMsTN)znHkw#0Z{j1#Zl_x!%daVRoco5Y3o_+o2 z=EUdY2)Xr5hgWy(RnPAN+EAv3x^0;kL09z9pJI4bSD=I&`ehxI9JzH^dS8^_?G=Pj zwu~R#nFU5b7{%7rjZt1>8ruOiV_O#OBlPrRGf|bsRl=_GgEJ8w!Xc@=LsqL$gp7{0 z8*M!N4@!;izoODl+XN0cr18;IYbqPu*3Z7~ZH+GdgQQ*#z%(ChM6&ubO=)8g1nb|7 z+62LP)j6vAyCVA%m!kU;+S6Xtrg;N}J5}f)N~`6)9yM2ndR_AacP7Omnv;e)fbu#B zAD>|@WFtEl)o$JWSvP|Vhr-^10-z|LG2q~xZS+|4o-13nZ3GAJ#i5qH;Z(q?R8-nw zDmZ!0kL;_jHe+;yP!kL z4m7$2IC<7y-q(4}&oh%aXy%y?6?X&06_i)8nwPEqt~?JE_${XV^F~`yhEELYU={Bi zHRiYKN6WJ@^0^L_4?p&>6NdN$u2^x__BPbCGbB|Ue0cbOISYz6#-=4=I?SA)3BKul zoX2bEzPF)Mn0%I~R7sb*z#QbG z7A&k?aWlIe&4iNwOZVkYdHEEz7Kp>{2!bo?oKIYPc|MQu`r*!u`IqoSPFi>1=@gsr z+MsX@a9Db|-Lnv_A3A=3PjUELh<%jyzPA8NE7zPrdZ5c7bJC1o+pu= zD1gt5RJl5Kq5{4zGSyTcuO315=tS2L4!u2cQiBfld`4LVLWg#eXNmhyHFckES+WnR z!qF1;z8b4Ssd#&S-I@V?ImTDQg6vMTk&mZxAzBj{L-9RV-K#QdMA6O^>4d@_dIwE= zVEoqnbhQ4{tv~v6)0kUWcUpCp#jRsVs~J7QwhRJWWDv=*QZBR@Iy&u9e)K1`>nG-t={-allm>>Iyp4Bjci^dnl_jm zbF7>9bPtCHyoTcEMwEOgvu4=Hw9GdHt4Xy5!Vzg6Mp14AI`TYw|2pa?V5Cu-XAt-z{ROW(H<hW1AHMh`AM_S+D;~Rg$l7n~bm{f_4(E7Zk3$?PhVgz^D&r=Dcy zlVw$s6esfKdu1=-)3c}SE0aQoe&*lk!F*H{B73xAb{Rf{QG$it*yTaL?v=maUD#{& z)LI=aRcO@^)uUX+MPw(TCU?}-?aR~Y56)K!;ZDd)&?r!No<8l|+Cygu|(%5SZlfBgee!jVz#Kv7u^>JocVQ$9q0tNdP6p0}e#%t76ysvbbKa`i-A z(VI_ZFL?qVUUKgAPPMa@m5_ogcl+{b9MS#4Tl z#?{~MOueF;FP}YO%rI1yDUuJzp7f@fNOg{Vq!&kWnoL`LMPK8^K}lA4RO~kT%J%c8 zWx;rlvY*ugC4i#aD%;?N>KdFS+1w{_VCF2D_2( zjgCO)um? z?Oj?Gw!*FP{fAqVf(CPcxvuW@bhUOY9$2NY2g>6GKB?j(bFPb@efY#;r_D#%t-AH@ z)^)~QUORDM$Z@37XD=tn$31BFU77kl%N*GuaRlf>-+2hN8?muEus;9zJW+HVKz=Te zL3sq_Q~dKqWjY5JJ5T;g)Je56Tvl^xjddkmd zIA91Niz_y{4_!pCm^P4N45Cs=s7QI5>$6~>ti(;GFMcX;-{;9{=TdmhV<0tmMOWo$ zuu^rH?~y^WQT`r3p!e0L2ikx+T%KA#4x$5K_Spn4!l7U9Gr!l)vbywFG!BDSsws(T zWHG#iqYDkfV?Lj0kb#%a*Jg*!DK*<%LLucjqY{bI^R6N(x|p*AtiKe3AYeHA0y&BjZfAqW4AI$gpcP#3`m37V5Jlmm{?U%=r7 zky~gtlo@u(_fa9oYlU(;bX%+aC!Y){q*OA{Nt6xI8RP?>-HVN0?dJ_UT*%Q86ud{4 z(|cCr_`FWHY86uCcSo{2LIhq_-hX%GPMjQ>z3`j#)h$i#V7yhr`&1mA{0Rzcx7*a6 zw!|OjtN{3Z%NSWmXb4c8{vH76ry=MSDZd;=)F-qE&b z;a*i{!+Q@J^&ic{UVGL(+A*j{8M+xQs+0o*_R{=rf%M{vM>d~dYs$sTD*Iw(r8(a% zb6+EbnNRYtGSmWvC-UPr+xz|Y_u20;{wS{t4$v4fOjbMk9KQK=?vZ1QZKRt_y@F@nW0Z zDiLE2`ilNLj~fNdg-@5N_YhUGx!p~QuxZB!J+HPtqbxJ9n(=OwLK%DaVu$WWMq>H} zBKl{_5m5Me;mf^4AB<_cVl7i5Btgz9l+Z)_eJ+=NIi4w)hA30?9UflXo5=@|#TR;? zGFGWC*GMtFM5PEggZHHY6XFKEAN8IzMT&c%_^(2fMURub{?p`LJvo8l?ACnoCq>Vwad&ZLgS(;((}Up#O?C3trl6@p{fD~Q0) zO&eW~h&A48$?*dAhRjhGJAYn2W|h4XRv|e<+6U>d6AFC4KTtGY145zVEjB2L4wMjG zMA<}gMn^*4S1D!;H~RsVvOsLAgK1z%(NK&?qNycCV^Ksm;%q#*l@bZ!TN7oKf^R!% zqP$Yj-AxldbXLB9rQCa#E~JP4I$WMIRckt~=)N-e7fA(yA@Cm0Kw*DAYf<~8CsjXZ z6|h@jDa|ytG{$3dX^h7wW-7pq=MuBLKX8s*aIfm9p8dd%<3rjPA$-M`<^^TYW;#Bj zq%360Nv0_5cf^cjNp?OL@3+fy-rn&Vztki>!CtGFDvvpIcxn~30O;^j~%}NXTI-yHy7iGcU z-czr#P?btl#PO^#LN-5-jImW~ue`BTKF6nxy`eJMWV}SMjmGwdu21&CF-hZo_>kG~N-b6Km(U|`3pkI*>4nU#eS zj)nfcN*8a$rb0Eo;-5N|Lm3_+haT;2*Q{M}s@ieA#uF4CmhcCS7Y!~w#T68^qA!71 ztUi6;TT~&@7n^cd_lM5U6Z_XmNC`@bV4REOM8ttCjp>=;W52hJYD6RJJ|&MJ_KfK7%6r!<)>&>cG}j zcT$UxpJz_)fWhKvAB4AXGiYBwa5!bkZu>>Xgg`7Npw#o+&(s;GvM^5gwX^h;l51zg70g`6j7;+haj_e#mLy-FD z$I2s|71{7skhWJjG^rdXH6Keim~-t|+Q{klv7{S_RLxiJr87DzGZd2{-elAAd7k~7 zZ!dp8{}HT3std-oE{7iDF`C$%Lwk^h291;DoE|@K%brWepf)Mwg?nkOQ1&-ka;Zsg zuTG%ww7~H897mrFh3au2Z~$p&sqymsDZA|ErHQ3)2T65EZYIHCPsNnhjJ(z9OhD9( z!BQR4l0JPrIme*aw^5cumno$`THbZd)^!pGR#Uw0J&p!}Ls%wIE>en&!8C}UC|hUV zm9KxVVQ-`!xxEu;lr?B4-{3{d~Sm zPuw5!+Q83>AXqRcJWWy}R-7GGdnq4&upX;})LJ3!IQ{GE?_%zTN+hXJk4e-8LVA9{ z4$&(bI~Xsqe(*R=vQd~;^kAq?F)e}jhQ1n%)pq-2Dm6stp^1ngB1p)ORP~`>PL-9~ z{dV{4Hcnr?gc!W8!CJhg$(qR5IM%clR#v<^)5r%+B#rreH7Pm^BJAxvgx@e+6;W4S?+;Ko$ z()q?xdpuicR4iWFQJ4mN^@mc~I*b~?qkqy6b#oLF3S z-b`8W28;7@Kg}|al4_NPe;KWa7ga*mgMs7JHLqH>{O03|Rt}i?s2ElQFUOYC_HbO> ziF!|MD2j-gb-bP)peXqn-@YDOE~C3Z5k&eu1RcEV;7*q3qBLb1MIBmc6am>b&{$0q z!$S%jGMwKS?I{ME-KZ&O)qM9~?FSwh2qmMvoTJmWzB(M;{j=e?=RvxiI^N_G-|=!9 z?%i>}cKE>Q3GG|@#98sG9e&DPsCQ1=BIs~abi)hu^*he|(J8!BPLW+x)fGh zw`fhNk%>4eGNlIiGf`_#G7UG;V!LSLUkHNw47xcRoA*CQidv<489_Z1kuK_z zUpn+B(Pm}{e|#kPxH+OG;kpb>NEh|!>?WKP&Bzc=bS7Q6I^vlz{hBVO=RZmn=Nzcp zFj0#9Q^f)D-j1`n7k1$cSp%=4itk3^h4F7PM6e?kHu@_=I zDoV!SEK#1SX9=HoGHR;V53)oB%FDtBx+~nssI6WHjS`g{vB9IxqeKTM{;WG~0(OEl zca->!8h$G_(xV-s3pF0e2Z`T`(ENk>BFTYL_CoAY6Ge5mOw2KRB=2AS?Qu!QWP_bH zO%%TLd=grnH5poHvIAv*_yabioh;|IeS7Of`zL}>=Y;U2dy~W*$|X^f#*G&r%Pjwz zC_aPA0%&`Z=!nl}zj+ag$(|r8mor%G7^l=sj595mAl6c|@dzX4=ZIahaD$Hs&+KGV zoXsi?wLR5lO3`wmM4KVbn2=`1rdocT-D*iNB}$jJG>gS(lWI2F;|wWAnL}AcRhCp! zvQfHDXB#rwWUtlf)X~ zkC$Y50?A%c8*5B8==4fkk}t6-H%Ufw3iLrPON4JNB`*$V=Gp|CA=wC(k2Km+wRUTo zEl$!Stz0Z>k#3c6r9W3;qWm}!Q})18*y{C9VP+*(BRWwgui2KSjWb~UVr@7wKqF=o z%)Z5H5kTWsiI3>ObWxTbe~OtBMh91l`qXT#sOE^r!qhSeZw^#kBdWXeeqQZHP(VOH zU|1lvTqEXI4C3q*Q=B!DILxh;q-cqusa5ZDpk$?RMZh+dNPcG zx>l?fz3J+F5soh$h}=IQu!-U4N z7l^L3eH_&BH9>=L9nGo4co9L@=fM56oPb;D>huCQBFWe7XNR|hL=z?ixY<(;IF{qd zX^)g$z8QhjMLA5F7v_zAIzAS+GL~Idr%S%qcm=R}Ai#O7*TVSUJThIY% z`PsN#l%oqAOr8F3GXNgmEaWe9xL0dXSgwoDUVmqD7gBZg$i)rM%Nvx-5U!o&;@!gM-mIxOZ zC%&_T4RQd95V@xMM@0v!I7?(x%281{%w)$xVlx_&SyS>AmJK^{Qw-@AOG>g93j()(}3fm6|FxeGU&o_=wQn{%%s)di_G%;Y)_k>WQt3Isy)6J zGid2?H~_!nqA@i-CM@#ki#g(|eATo-_%-BZ%95xx8!d^cNh8BCJ+*L421{%jyC*5d z8o*O zFFzM+e6_J+JUPxrRUdtaSu|x1YoF&s&v6(aN$0SU##DBK2&33sR4V0V%tl}+F~|G@ zzjSdnm|M(N=Tgu-{Ev?`{Ctotufnm`WHQbZT2FalGg?NPY*tG$9!*LaG<+W>CIi**iUvxo^)Fb^#x%@EZCr84o>xL7j;mu}2P!*Ff9 zF%^p+och~EM{7?@;Z|t>eyn_}&qHmv>PbN}p-O4_J3Ui%DCzs*cq$(d3+TcW;p-c3 zG^QjQZHY!{)zc2MTji+|XR^hm*=fsE;qLa%>TfrWNHbdEWbq}1IDCsGLK=o8Q$>{A zrHuzfb?NhSwMMLODQPyN7BNjcto-ddu1&Cz;UMg#^g)qEhYkuiN9>E~{6R5DmSjX|^k ztM_yaMg+~VX?~4U!cvm1pT%r@l^`0rWLe|=wf^|4#W7q6qKCjI!mm9){XjM+S{!QN z;SjI4k@h$YmVc}%B}o6ybws4a8f!NCgE-P?S8fnGCK=gvR-+E*un`C+!#U9yyAQ-F zH7VeNC|e-{EpS~CT0F?0+2=)TZoCE)J?Y22U|Y;rQRgulNf)qAOB($xQIvDUvlM!k zh-tp}oG8oxOTpqvZ{r%1O{oY`gH)MJDTsjWk%oAiAt52tAOARoml_b@noU{qh?5DP z#?K^5SBjH)A(e6kx$sp>W{A}73N-9-9&1m%L{T4|iB1%)%1fJlIXXnB#Bn5qbE6|B zTy1_PTnNvEhDhC~2$L9`f6F8)Ipq5fN8rN`L|EnotJ!Q#$F#?p6sE16gKsT@aYKsD znt@mxy8|u!57n3sWBbL7?=K0;Z=H<2H$AuDzm##>k-yF=S~*fZGa6lD79A=3A|{&S zC3wvf7vY!MUlLU#L&CT*GvaSM^pg~Clonr87CxC;n`#;^1zBtZaOXV7wen6WGA==0 z6a8uPB?J$huVYy{cS&e@bB0++v##M7TpvJRUW0A-xC-0F*9Bb_b@Izx7WW-w8~pOB z2*g)aUB4>k($gzqD9ybtlFPy7sxyf)F4sx?^>toa9TiXIMfgc@{P45zyjps(k*;e3|g z7X9T}dG`jaDf=b}BY%c*?Yt+vJ@^PtItw(|Y=%s2n#E+b&=wnbZasu|OuR3Q^!Gi4 z76tc3c?YWZ5bh!B0d$M27BuI9m`@je7p`pA9JiHwfJyl2UDTfNP>iCW`v^T2{wyl> z!LpgGwHVVSzx6iq(GE9e+LH{nco@Ji3_luIoQ-q@fEBfHq$FN7TWd{WW;rh2yjhgb ze{)B?a-fRW5fpX!P1xifkG+S$A8drZ2FDdZ0jN6*f2v?Zui56=@S@lyE4k)aTZxE{MFsbALbXSuTa eKU2-;LRT(DxzG4n;q-kW8kDSx=A_T6pZhE#fZp_;jMHIWc z3$eR9Q1pAPIcI!$p7(y^_wVm>pO1U4y{=truf2Ah!<;eiRIPg-Yt6K4X?z+Lq0jsSVSqXA>^>AsK~g)$dIX85{U`qWMF+@WK2X@d}LxmtQIq^ z)i~n_s*`~ZN{)<8K>VJLL{b;>C7?d=B#_c?)R0K@fYFiBVYZ>cl4Fn!AV&lx#Ey%R zNPg55)F=Vg0Y6h$P;-OG4?`uykBp5Ar9KUUjDH!KJ;a0+$cSjB8Cs!!nL#iDwg*x} zyU-w2a2}l}#ex!2VnRkoCI+K2QYW5Q!4jiETn6;?uh2~inA z2@$CDG6?F~Eo(vJGN3u+u=x1cc-ye#^G$?;e~Iann+o~Ufu!&-Ad)gqiuDA?2Ze-T zj4GN5`IIp;P#IX33k77P~YoTGOIQDZPlSMPWLL(~J4Hc17%xWVvcnb(? zW@Z4%DF=xS8QTdJ)dEtvgs|wbVet})(q3@dHbBbX1V}v{)>cqBEIBSLBvB%Hk8+f* zg>;NgMy91W)|!e&CB(*b!jOy%i=i1V2@MNQ8VNa?TprhwjzR^GQ4#gLZ)b@F{+2ld zd>!D(sMz43s02x-C?^0((Iv=F({5A(+#U5;IneaXkYtu4LKPeVl2hr4c)N>40^Ksh zP=P+M7ZCoIdDT&Hwq}qqjDIZf(n;uXN)T3FOxwGVNx{3$!h(DWNQ&$OHUMq|)~5M? z5E@orLn8TK=4C|SsF@`|GawV?*3g1XI--~08%KfUoTVbhMaBmu z!p&ErcFJds%E(gT2{hpo6UJehlW*|uf@Kn;@ z)%OP2pESqn5EVHxBJnT^kY>JUfEtbjl22%yb8cTj0cY@JsS*7IMMfpqs`s6+gt+*~ z=pcz^&&ca9DAW)6NRjZ!m{8lKIEn87p&ic*F@pIX8vAPq?c5Q|wR2c(9V z1PJnEAf<<+JSkd;^3;)E!vzI2Ll!rBq-|&<{7*9`p8w5Ige7Ag##JA!Q4iwcW255| z6C@o21;s{3g(bx!eX6Lac95{|e?U4Z7M2_q0!m^Bm#hytHYO|)hbRe7QaFFuhR0YV zfi#Q@N{p}_9hPDOnR;Fus2&O+S>P*bAqB=oM21A5!pH2-nRd=*G11)_sS;|LcSzYTl_HT(_<!xp_HZfVg!G``NIEP^>LWjOzvdW0Els(a zA|Hv9Emf__ui-WM#1nVMp9UAk2o)yAhlNFkr$`#0H1%^D_&Pun_z`(TQc@&_Od^T1 zjSr(~{t7%PB1puKNeW8}`=ju}B*A``V+D*(N=OU}i3qEUax&V&ULyhCm+3uDXy^fC zGW1s{KxhRE&;Y!KtOvXSr2L6cjO?74pw>q+7fTN1*PIq`unV=tMA67Gse=96jTg4S z-9SUy!t5sqE@la&o^C_}^+=ros98S^z*G7FR7B^i|84F?hsB~x|2pbw6d9Q=3}rkP zjSN~f5}*Y&xF1M83!=C(`pjT#f-EC1*3xKu=tU*0Y{FEiH*msQRN6j(J)sqb!39A zdbcWsOp4b4s&|T@ghcqIBt9%Dfiy9lBuw6NAa%6GWI>@XIp`@Bz=T%U^brZ9P**fW zW0?UZXzqN-6Do*{QmP0)NIP;H5ns37>4q=P7jM8uAc3=N7ORUnvhFMF?V6gUFKsUPpB3)MaWk{T62 zswEVgA=bu(_cMf2E;9x7qhdqVNA~z+VKGWfh>FDeDCvj#NbTi~(k{O^(LJ3lGqG`> zWj~~#d9h0uS*-K17XudT>3nE^qw<=S6E~KPc%9aBY0(V5+X{Jfvi-;R+37*r^|HD) z&5GfA7aN?PKiVZ?O6BBw3tku*-@P)Dy)$X6Yi6yrbilHXkC~;ZO>5x}+9!H;rq%v{`1G*12K9d;J!Eygwk^qGM(4GT*|j!!4u_h7Wl2CeDBV8=XaW zUfcK%xZ)M?;pBa`td2w7g{|_=Y%#x`*jRb$%e@Qh%~)m~OI`UQ)!`L2El1C;>z?r; z?Cd-zV#KeWQ+)ZqrfW16~jtyPEBsVB>D__1!)(3F^rx=V7|sjN%# z8HNEtyGs`|(d1p6JU-knZ9-p*#nO8n4R$;o*tmIeJ*{Eu5|=Gqv1Hle$LAkrwe@T` z>_*SSAt7g5e2izeBTD6d<)zQt>>+7_4@0R@Rz9*lnyH@eYLy;U;VC}8T7@$ z3r&;Vv}*kv^=gxTiFE^~^mPY(`fa>8?)7z(POlfs8ng^6I2X}r#A^FCuM1PlE$W^L zu}yKBvf_4otM3OZoY#zs=MkQ>PlxbpekEPh&6uBb z!n*U47r8cf{kIOev+>5lOuw>B`}N1~RIKu@T@>1K(e&lpysOgAd!HG7cf;P!g_V&u zzh=~p2)tA>Yr@@b%f`*zc>BowjZ8~Wgy_huUnnU;49FL6r%sCz{_PLkOue0NO<6AQ`my~EK za*Pii?qa-QT%c(`#Uh_tXQyXNI^H)ub!^p+BUg*B&v1YFY{7y-_J=(i)_>w@ljnZ0 z+0oU5T9}Q}HvJa;dY#I8iru~vyKe1mE_LhY-OsCl?W@zhS9u+m*A6d7jh`fQ?7Z~l zKo8|h_PSnc_udbpdbT>aYqx*usin6T}RMx%E}(&83f zKXds5zvY_g1gj6R^Ul{v&-3K_zg@m&$cYKVSY|zAp+>+$muW>YvBRRfZW}euH^=pgna70_y=N@4 ztoWJPX(lsn&^GYImTvRsB?svpS#DDeyEIhRPG(n!mdg2f}tiZ$8>E5=^ihh)JLgW`6h3sxy@_+p+?2_aG_$eJ`g?c# zT-=t(EHR9JeWy>e{V@CJgfluy3QojhFBHO=4OJn$216z6^3@2PKmhOgs> z5e4-)ese&NCbjrQFUI<|H!qmb_td3?{lBgbbe3J~+iT6s8TUID&0X?J$1>2(=KY~wrZ1pMmbMYF6q>;Z{};0^#Ttz zmiq5J6{g9r;Whch-M3wlhA8&3{Iz_|$<4DzZ8%a-(tGRmhOG*ge`~q@-LD;f&wpPz z?eN-hen8F1^;liAu64sVD?{oVw%p_}@m|O2i@O=I{$|GPovE>L*-5tvv*!=Y->}SZ z_OZqFSN6=Y3U_LFV-CAv)<4j3vuD6lFSkU^j2P15VCSrvgD-uUu(9j@0n$nOPa^eA ziw7k9cRs>ZNG^-QM%cDxr<(xkqJj^QM2k%QDUUSSHllVjield;NtA zj@pYNSlz}EG91<=?l?1X%&oUVdRD?pFQl`Kk9UPFQ2Fn_#kgbA*yM46B zSu13}Aocwtd1?zerHr#w$Z{Y#s?*%MIp{*@tQHOqQpi62k+Lim(pEaGG(jl~&=K-$ zvxChPavl=tjxI=QvV(nEv$)2((sw${F-0lsQbQu?p{@<(WoeM8A#Ijrp^!eP!73A# zQj40*F-a-&sVR|oA`K=$&f}0e3X+9FrmHKFbW_)Iu$4mQ0jZZ-LM^g|kd%UCsgU2) z8gpO8DGBbTm?PSk*eU@selpO;}ji?PN z{iV+;K|13mLU1tXp%VkinYlD~lCH1AO0AUA2X$B_z_c!NY@(EV;ApSz0u(dFa0o^` z54Jz*)l>VE1s++D@*F!DtdNG+W0e+4>AHH%5sf`S+CWX3j*9`BW@R2uI+qaZtBzUL z$6QdyA`tUX$F?EXLmm5qn5R0{tpRlvWo3DYkzLGL)-;85h#^aDrqnr!+v+YXt(lXo zb3@z$A-NvQ@>IwQA-O>^WSqT1b`264QHRlp)G!i8Qk!uKg)ANtb)yDz8|k1c3do2- z{sf5zS&PxodEm~S+)P(3zvh?TZd${OH#0Qn{S4s*Z{61j}F zTD6&wNYNUkn)H-8bF@)PyESH|sCH&!VG%QAZkTO1AW=??jierP>!fxR9Rmy8AhIe8 zC!O(#c{3MFC+P(XmTIHaX=#Z?Ox>+y#2i@_lD1j0Ql(P*9?(ar)51z3aa9lLJH%+k z(o)-4X|3rGjYb?K8a8$3r7x{nYLHT=Qxl0Kn5vZVh*5vwoLDPwK_W{@7}rrDH*PBS zT$pbrKv46S1p8wg?jXgbp3FQ^-z0@>EN(t-Jw-Mm?H> z=UA!hmPdm16I&FWq_M92AXpj|L63vTyG1GE6wI-cQr<=Jue5)ame+-Benj`%(73&gTl1z!cFbaH^H?b$wML0 z0AwsgWylR4C;OU4@1J-?P03o5@@h zPO>pw@t~2aVOfn8vOAE*{gJ%Ut5}UBJ>ten9h9>67{M$Jsk0qY4l8qTk}1054={iD z1(1S?m;Xd8hInW%I&r8>y9XXsQ~T0eJy@!vQq~(&%~w-ex}+zobX4ld&_7|)#UVxx zAe^->^kR;^l`{R_f0n{F3YjM)8WUu(QRqyB)LT8xP9lbtpqZ1jwL2^IP|8Bwh53UM zj;lht45UgaD+h^Lh|$8XC#%&*s2QgY9LoAYqBLQD%!Y)a6^=c!{g7yi!ZR_&bf6=8 z1_@J4+Q)-cLe1$QhpCHW^OC)QM2?Nw3rCu!5@ru}Y-|K)Ad!;^ZeGKamG)4|d@*N* z_GlkxkVqG-&)D$qK!W1X8fiMsy^zMrx;n{x5ThkRy+HnbwNsFV6h{^th3pU{cn)Lb{mamiMpZQ8)OYJLBxSXS}-KiOudQeEF+1|da^r+k^UHN zG}&+L6c?qOIq}7BU{%aN)4-z!5#=<*63VwGQF`8u9 z63|Mc!OU@}QZ^OSIvk{6toM+_uHa6{)|*u#OT4$>uNWAGLT4`|^+7@Q6)|DJvN|br zTwzxAK}I$eF=6D<8=a$&gl$S6b3!;`^g&GR#yZnAG1*hZs5U)1+sIt~u%|-85d+SU z4@t?YlukOw5fe6{2L2MsAoY$j5;66OOjd%J=(1BBv>^!F@~|O-Lb&^aLUSPr9k_^? zU=Z+fqoJao!KOI9;LsmuEzdjoX4>9sw%%F)5 zx+4VF5oV*{m9pL-1@9sk`8Qwt-@GdgMQQF~TC`H=?1!YbmGsvLRvN05DdAnBBf$Qt zklNFcO6M=c6l$xR2T3GD)v;v6)MFw$iWs@9u(7xW3nmbbATuD5t}rdmQ%50@$E$CJ zWL1!;r!Xv*1sANml%_sj>LfwJaTNDdn-S~wr_6guq#+E4GPa?Dd9d42@~p6n^k8jBsW&&>`Z?u?t#i>>Vx*Ea8^1B$Y(6 z(g>y0K9W^NDF1%33yc&R#&pCqo)^hdBbCxiC>N=eX^#>-6r&ockSa$p$5BdY<|vjr zN~x1ES|aghX``HUZXo8Zj@d?G3s=X|5$mUpo&6JQ6s;aul!!zOPC43{i)N`&O3siU z^GK>tZ|G}cgm2?$N$9{J-jd3%fo(_j0NYUQ+O+w%!3Jy#Ru`;+a0X11>4NMI5({QG z9P=PKLBdiFm%jc-;+iOA264hfj{ngP2%5p2Oro5^~W~nKDS^G{PqG7LrgOo(btRi&x*y2L5La!@>X2R%bp*EDgD? zAV%&0O*<)M)(M)rvfu%JkjS^N;`%w%g+N{mgGk7NHo_UoTUI*}wnu_sR`F&?mJ7BW zSUvTgyfcwGPEg9efuvCRVn4zYpYg<0%60e{;Tr11(_ z9wcFHKpE+|39Pi4@;?d~rwO}+4n5A0dZw|`9Gn0^4pq117V`gb9e$0XZBbOF9?`^f zR#~8w7N;}E=}OtVbj{*KOI-U5p=IHzM+T&>YQ<^!ISGl}NHDw(2231k+<5keG+2E< zybv+!p8A*}yAO%XB^=kxvIJ)l9yAPqB#Z=kY>}8ItYGDkx~kivG_#4C(;4a54-)yd zdRfuRyji{Jvxm!&cw=tH0lesNodl(K+{i}f60(~AWd+EvykvG5q&Y5 zUOiVoNMu?}CyeD{NMuu8wPXB()D05)f?d4p456P`r{>@|42fFC4QY1;SHe=5tNgc^ zqbBqhZq9I=(w!-sv9RBEQ%IN2WR*-Qy9$!*iPOSF+~~~ub6S|FkSb=e(m9U)dSnCy zZ3KM;s?-ocieQ95S9K(hF;=txj>MaYJYh|iR%nr-g;)~=s;wCUU4Ms^&qkg4??_s; zL7>`g#dJdAu|KH!_99P6`QX>;3z(tqnu|zOM^Xr$t1i%0OeZ8ox+73}PXxLMsbVZC z>g(^Y22wo5bVADSC1JsH4KgSR3$*(BJEW}MV*1}9spKc76Ow8}5U3m$WA#Nyd;kKq z7lJ?+5G$q-`CqXPa$rAKKjXkAMqk&FWFwGEV7jTV>PU*g-PMY~h1J)8MWKDke@zgK z4WCpSeGZU%R4C$HAYFviqeTeR;8Fy-sw0(KMkKCf>d$I83Kb**ShoF*DqbtFeUPb4c?ZNy2~;?+iKgIp#K z7a?hP6@gm2CgODwZvg2cG(>ofK>6Py&{Z9&{5v%(AhrDof%wlN56n<6d{rQ*qTgad zb)*97QX*1C+G0J4%(_n#t=)PyjdyFsRgdWk%t z4rCROC{KLU1r7s}r;aA_zd=fh64R?AbvPzNOo#!JYbS{^A$eFbkf;=VkOJu>h)5M= zigIE|5BuFUnJaRA0tSMCc-<=qyntqymLNs&Jmj|6h+_Ye~GwB#4RFj6LE)#J4Gx3($E|i<&!|V{v9#?)d^Z< zu8J86DSA!B>mpA`(HkP(6nR4GVYw(1QuMYc6OzgA1IeO~fNKAHj0hEc3Z#pWy!y2$ z6H@ezC=*ijEk3B+dl5epiK{wNgWp8HIuc(6UcF0Fgev+iW+dcT^ai60Vx{yUB4yBm zOsFlQj+kB@iK>YYLK!}2avG2zBK6-;l&d4v+YmgVkrb-~Wi%Bt5|V5#%7o;iRzRYf zh;j=c+0Pb871@bs52TBbqV4cO`4m9P=Rl;0v^sc7&D1g?!pIE}GZ1pje6djmo!W*# zBDDg5q)rf}0)v5M=8-`BlSGRAC?MsF5&1Zg9|NR|kjlr4>4~CD-*_N?tcc^tK6D|X zUOUo(_=nS&4w)=@Tjc+s+CRkvDp-LGWZL^ck{9!r$C~feFval5kZ=TJk!9r_!CpbV91d zL6oZ_@s1)-NadVFxjIrex{K*Ov?QY-;@(8eNJs^Hit_)2v@LofA7$+)<|m|q9wf?y zB>MuTtYC|U+A{)30y{#?^>;|=K}aWUf<+7wF%(GVi38I0cSz;q#rz3kKA7>mDG2h=Ixzl#CD`ngvW+WuJ zSdy|8sLH!9A(CoBnfi`p?bjKR2heOZ{_m`p?a&`Yx6Bn160g)te^W zr2cbrD%_;f(c!<|l&Z}H{-2vunl`xp?k4r0o6~=8PH}?&=jQbP4>za3>ikmQrLy(g zLb_(X-n!_MNx?6CetjgOE%3TSO%9lCyy4Drp@F z-@XN8n-V!+*a8{qN%#ju+yK$j21I=cKidXG-fp>G1 zz~makXX)Mf%X0R*9*vEPeLv;7H$IqlYfojL^|3Qf`%Af&WVA(}rb({ibuGxEu=lQ9?PE?iWeynL1ai$^_9zFYb1mqowt zm0ClN`94YXzQ`ART<+}=x^#VE*N450v*H$foixJo)!U_OHZS-5Sgjpn3I750OHCxa zM=PMIgkJ&V%=qUuIbY_!SI&FsqMPOtz7jn91|py}r}DBOO~gyvJ7&f)v(~IzrsD>M zU+=`({T~?pE_|b{zpB=aYn=xF-1;QK^-)){XkP=!0y?c<=Sar{<}CUAuRDP(5kC(y=r4{ur21Y2^B?&pbY?&DP4^-?eDn{O0*h7g(mNSkxgC)~Q6r*|V$?UuJVy z&K^T*#|{?zvKx?^?No6c*qEKZEboY%U4_(%S?%&=4oBrIcb5upJY0nI3{v54l~!fNNzI@uSdJPY~YIgg@ZY^8wD>d}HPpqSQ@Ve~Rm>20e zijXUble-RcG)j8#Fefy#-)mNI%s3;hecc0F)4Q2%*`5}Bc>6GZ@Hq3Xug#>^tF6=W z`_0+Xscn0sWrj!ex{gb^HZ~-7OXjAHwf8=pu(3pHQlp`Hx6HBC4Cho`xn&OmtRAj0 zov}RX+!>4eO;)Sgj1M#z-&kw#xY!yKw}oWvd=}Kf?D9L44(Hrb5_%o&72|8>-D-@y^m!f`doWGK}95-g>#VXE)MZ#9!j>|KSd!K3k$*ynimsa%*MpZ3Zyy|Fe&z3EG zZYOl+PoHVlGoqh&{~EnNwkwQ08B_1*`1|!!cUX>{eN%BV-9T%{M&Bd!2WZW7cCD_f z-0fP|n$mX-9t@ay@l1^x`{t}OE?Lk;>uyj=xBN$D2USlNj5ysRxN*jvom0kcpW&Ft zU+CQIyjkZ(=~>HzBf?95=BO*ymSh6EB4{q{q!^RdLn?=DKO4ABZ7K(^oSahy7^Vbq+!=vHQpaI{Q0U5bszr9+WIAP!H#JymewA3 zzt8sNHzPdaBePnq9C+mCjho9HJ`V^CYJYjg zg5|2Z2FuTcmR?!8FnvqLk?8SP?)a`cFmA2#UG20}_UF!Yh__g!2z*(*-JN&cziFvH zJ@O=tsbYH6r@6F~ldBvu6BB)AJZt3k@x-Ow%cgF5WDpb>xS-KagDsn$xlA(q%co-B zlAApz^Hsf9UX1FiZ|9@uP}?HT^w5IGFCO+sMfl67w)*(dLsKhITR!Q+!Hs9P)S5f9 znX#|pT>plb`WyB?liu6kE&j$@>x%a)t-|~r{GDH%RvtUL>38Mhx;1Yc=(BdUO&gb- z)kAYXKcb4Eur^ThOp>bCjy3#QZd5wQWt#0~$tpQy=o^N|i?|B5bK`xDo1MCMveNLl$Bo9NZ+pIco6@^&bf`t0dLOrR zOgWamSFN3}0rh6f_hRcjE$2TQU`_3VeW3xZsb}PTu^|W*mSH0hCqT#>aw^V?&9Cxh z$!F!Ps!Ap8hjqLml5Ngm9Y?Zs05%Y+;0A~QRKN{lvQt=v&dYg2Bcyvv_+YBf;ewpK zKBB_j)8!}@B1nsmsyKi4{g*GBcM(##iW|z@Zewq{Bxj!?1+bF`F<~Lu9#U~5*t*}o zZ0%(^E4r=Xg4oT&zRd56oVlRR5SD+$m+4-`-u_#~g|Wy3zN`dNF3OE$7Z0Jo*W{l2 zX1tqcT-(}8QXc0zJHcYo5=;ZNJ+jZWsB4&HN7R7b9$Q{2O z81rTS@oP@HU-WJiNM`cYj2OvGpqlY@IZHdJ;zqNBXz&Ci+czqFWm5|v!{3&(PUlqgb=g0ccD*~rgNjZj#1;1Z zuHB-B)p0{Ci#ag5O;^zflIS$!1xV z7{Ysai(L<5F6;9VV|Y)_HhxrblbOkDjNyHl`?ZS8XD1;UKady7k#j0@gL|HMAZOmc zR9pcs<4|q#LwR8s5@!@{g=F&xJK{GLH;Y+)$8HHJ_q&Q??0W_L^s$^3-%)XejJu27 z@(ElB63+)wHP4>N`68T>xcTh;F<9%V+;h3_Dpy~<9Wy3+Ivw}V8XR{zs&!SzLxI{E zt)@)4-nCb(-E}SRTpQC7Tb#$`+F5(+K7Q+v=czyG+)bC9@U#5}KdUwb3z^9Sc>6Os z>j`gP%-+NIzd`b@P;pDy{0}hJbMzn5a@OZKZ1qC!Id$;VU8=OyN3U`m-(1@C+j^zxm5+7K&l%bH{;RkVuAvJJc2;YC zB{Mk#i@%h!vMVaCi1}ZE!C%TfpNHQ3IjvjBr%G+$~nf*TU*V``GLtqX{b$-Zp|ZnvI;k-=?{= zH+7%w{7T7iSek7-|0t9f337SYqGni^mn7wfTu@V z4Bv3~)K8uBkJFcI2)=)(87q5j%)BqDyfj~vqpGz(wcEIJ{*1lT++wRX9V(2dxRw9y z&8!ufI$i9GYQE~eKC81!|C|rwo;5n|Z^s{UGkCWzFJV~DjIa~!cAaf!`@`-Ki+*FA z(Z?XUAfNA5lvFiN>6zQ>WA4gEhNt-YWm^(kXocLp9$L4qUQ(N9sWY9=nvZL+ciK=Lf$`-``AY_nFAiP(;(`&6*CAayO67c3pG!)AZwA-mF<~Hey$Ca`yhKziJ-d zVtXJvch5}Ek7f0ytZ)6vWcBNsE3_Vrj9=j0O0I9%cKZt1G>7Nu;kqN3`CDW5_?(K{ z%G#ax<+ibWd~Rp=&tsCkgO6WOam8%b1x&K{@{HmVuaaqAV|>0`o85vRJ8-(Hmfkn> zk@g-3mYQw)omNrHeeepm8oi9pPbmr8Vt;qQ;zjnezV>-u9{=5ND>wH>*ZS3Zv8#G7 zj=bHvXIV#%{&j-FgOVo^N%iXnSc6Q%--H27ZH_q6ZB)MTs=YiBin+tOK0 zSKRNj^^jJ{fE0rhvsVmlJpXmnh30PGYkQaK<=f^@8E4SR#QOv1csj9i2@{hb7Z?T9Kd@yFs&ZxLOEb=tgj*r+yPOH4isyAZeP^_>G?DO!!weLGNOljvn z!t7qhG;YGk$PmQL?`FJ|}cI{H`kwiA;tH9xhY_r_7K zaqqVOsFDBr+Rnzyhez^tfAnluhyMJkvA}*7g!91KPx6fLjj5$xL20`2W{rET(K-<5 zY@WDqwyD{GNm`k=0=G)8naY(_i)v0upyI_DNV%Ql|8DZ22YrTwb+G z4_5E7)*bJb>psmYAH6NXF6z+MxMQ2;**IhT&$m}kIj>%ll6bvGT$?rNuD)+3%xT&4 zS$|K9;j8EG@@PKzdG`2Q`d*i2??|sPueRg)`a0Ven~ZKfZ9?3sId3l0Ltjmo4_DW2 z_*avu1LtO(ujjor?NCN-#Rk8ILmE6O`q|1U_qJER!6x~iU#$!H;b3B7oPS^s3oWzu zh#%Z4&8@+g-P&LLTUaIFO~}v2Ea0+=JIZ8Nu||K9d-k+n8FnNf>`KowXEyw(*=E$r z)rA!q2CMGne#tV?Hm{1jI8G5();!~v+xS68`}Z^Yd}?fRe5Xdix>wE2$BozOCwxa- zI1e6YyHRPxS2;7krs7Vr$ZObJzrn8{on|K2vA04>yRPESvXhXKzvGy5L&cqEDL1gS zR?0ockBlxZmtCFnd}>_UfUK#93xe|B*~Q4yq!%{*4t6yfEcZUyw?_upz24rf!!scm)>3vdGM{8;V!b4H?c!k%2~lp6?d84gp~IKhrC-V?kXFD?b6{V z_Nx~v?mCmb#0Cv1`lZV2W_5#aUGd7Icu7$9gE}!P{RbC&&Uo-+`7M_zm1cwH%&Dka zar;ppXOAUME`DzCUX^i*EpBs7p5K>?^OsyWHNV@_Pm{x0L6tEpI;P^v+3uHvbm&Nb zo85ft%T=)Z@32Mx!eaJb#ocAI-ovkd%UK0ZefL?*x4wmb95jF1TZf*CJ!I|P`SQ9P zsKR$D?lG(P%9k%8@#+H=_mo*Z^yMR@5I;XranG6CQ(xX#3u4hz759?8hj@ZS?`JCR zHCz77mrvG)7>2&TW!wv2-bM$a7c#$R^O5-miN()V+(-5une%EuT#TAOv-^*Id54-1 zY2o&krjdAblQApT%2ANlg`GKd9_R9qFi3Go|=E{|2*Z|1+x zmtU&~v2348%5h9@zYp(M3v%>+JhkIkDP-N+kj)R^p&iGjJoe#BAZJYKVAzG?^mO{-{G?x z-hJ*feMhruK2j65)m++zch-(?ccI-vlk_F)hFp6XapCB#8!Kd!wAR(?(D;tGZ^4hk zS9LzGT48eIY1Jp|9d&vhEcbV6P}0Ko;McIvj7R1;(Z>C-;hfRA`x8_WPpikF&+y z6tPS6TK_N|$;;jxm^Q!5iYJW>1BUHi=K8?VO_Ju*eNT_+KLRJ$_kC16^g`?8CBqdP zPm-%?))4&2nzc6Sy@7i9Ty3;epW`nPlUEN+Cu-Y}c>4$3G5WQ4Nnn-Eih*0(2A!N>*`*`wQf>*tB3wU>xN}R zHja9%C>l5a`okW_qMz;Ys2Y+ndsnVq>i4ec>H21epTx_93O^oLcs+U4zRUCG1RUt# zQ#yASUuFWQDx(`dTl}urUigbCCPhG*N@~xs^=0rDGstpGqIMh`vd>4_UOktj9XJ-e z-$&X}J(HxJIJV-K57(J@tIzpz3VuF;1OJ|&3*V;!Ixw#>SDSr0>M3>NShr&sQw!8v z^+6?dLAxJ)_-`Z!d{RkWIcECJhhJ+6IqjQD>c%nYXG~rz$YGyV((W8P^c9oW8geo6 z_vF|p$R#9~A-y+L`r^Y!G=XgX70(TzFl6JVkfXogu>r>}eaB28`SVYe)C<3v_7nYX z2HE8Yo*Q5>_mhrAf+131>I65dVn<4Tou5XT-MJ+B3MoG}L8n?Gob4m#L?Xl4S! zmmgz-k7pog*^~NnY{66bbxUNpN*RXoR;I|{-U>vnDTo06A`#z+=wt?B1fOLF+XeDB z34-``jR3)XK0ye7pCFX)Vh#x7XAy++&k08IZjDht zHPW7Kf10!D+v7psc)2}ioRMdKe(0C|8yx*&<~^%uTzc!xg5QpgtDE;8?|Qas`^55@ zdp`LXX}5NsFL`mu>d|cy zyZbQJVS|4AnF0Osjhx#a{Cp_%=C;%Y7BLA%VT;O-n_PXnVR^pZyt`h<<=bW`ubzEa zw(QlHGm9Nu`7%BPJKY8htnbx(26vp3e zYhV!vHe<~*ODI_me4pUd~QIc={TA8WGVRi{^Y2(~O-vD$3xo}}ceNB2+stUY(n zM?ShO)SGdx>9iUj4H9ccT3hw_+`MMS9q;iw**Fhnz*NT_6VjUG*}rue^yaZ|!1#JW zuQ$A(+#zweae~8(rfy06^MtI61FESPTV1^v?+%_Ni_7{%O{&tr9Jr>K76i&cli!2-n<=_grp|$ z!ZEzR6};(2JM4@4Q_{KSR!jCa|9bzx&k07^C11iS-$zC=fK5?K?2g7r%-%cyv?dqHLN@rz|qJ^)1#OQ#L zEl;$$IrHT?KfkDB^?hPrwCZxXntDmq)hlSS?{V*>`b(Wd9voeH)U{_>O-`)9zk6QagSGrXd zeO)%!Ruc5nIHa0-+f7QFgxnFF8d_!(g}0Lwk_sL8h^1ZE#aMLO$Xtnd2Nl1q1_{*PZ#Ht`dGKAerg?;YxuLGfgpw%z z%b#;@tILJl}E=fIX(LEz)z$9dLJG&ZM6OpotqZL7QX8O2+6!otkOV`IYaw z3Y%fE!y>Y0UK#v0q0oBz(u@aAD;M)+ju@h1(zk%;NZ({9oY02Z?Fy=yGsey-WbwW1 zJBi1dCtF3XnsB^iO;}o&=2^R9)>kfZ@=N*rq0O5S9T&~9cDmj8gXxA5y^d5C9P8i2 zbH|5j`p)3<+oM_=XV~R+d$co)&uRza1`%Zn5R8{OfXH(J(a9M^A)n<8!a)h*F%dl9 z&IQCXA_`qV%;)bDG0zo5PbJ)GVRfram+$UudG)vN>0%r0?ABLLIISsL**oTy&KKXa zzQgZ%gdCOnbV&N>HfN9OY~r2$vN|)i+&9@>@Y(-K)4WUAn?3pHVNjn0IqU zL*KfJ4RK5P_e89915xCP9LxDWT|xMD!*M1I2f>xX-IQ*3$aFVVB-~AvK<0CMp}-n` zfF}w>^Z-%p31S_Or`T|mo*?92AU5#+ULZ~oQAWf@Ue*^xaxV}SRL5q%Wp5BRy+IW8 z2C1Q9^QL7wXd!p{ptST_)d`K?6g_61?s9b57o_utfw z4H#52SZCOT(XT(=xjymPm;Mh9Cr@`Xi`?_;Rr`qILC?RuuBH9qd^P_(&Ifgex)J@L zu6YmWf0B>v0m8UHh@;S-JI#;j3E~71S9^ju%YP@MBo6=)?EvCDzneVRW+2tk1;j-@ zvI~eCM4Tn!GH>DtB5x3gG)E9u`IAIA3a>}lScX91;s(;(5bMZt%;w-eae-Wre+FWyOMjp=qEodX=?&s zF&G|PLG@~0E>+iSwdb3S&eDc%0XB<9`hSj2e4cf2UU84YF=MtL%d>pdaOO;plk0}I z-rgwsWq0c?!5(HqYxi{aoSFVQXzcV>ZKAik@&(?g_h?^qpq#JQ4@c_Td?Y~yKc+w6 z4u6v1E^jpeaF0(RxX)h%_&=!b2HRaPyxSNUkaWEFiwzgT1It^tlbL=kPq9-3=)Y>+ zfBMe+E&Wg4w@$w>-Sdp}k>x9Sq~bX6`uL-0jHb*bgDAu1`8|QD?)KZxfcw zc1IR(uhz=*>e?se-*0T*qItH(l3r2IB3I}5w~&O6w(oLo&;0hcKOOp2cTul>ds8j; z4B!3oh0n50E{9M3uDYXN`mmeP@_=D!@hLUNRjc>~KWi|o^RjyV68U8x*Bx3Bo2+x1 z`gPmCb9qROjVphwJomhyL$lK#+i*d32kPIB|FmzYOK$MfF>?=a+jh)f|6}~@|#sBo?8W>W0%kc(WEr}!(QT4^~(Y~Ao>)N<2 z|85wktuq4eLe<|jz>mWt7&Xz+054(jAhOkRBmBpXcH;ltBvgRUe)#qVRmvY2%{9<9D&NkURHsaxBnq@3PD{IneIyfQZr=ll9`tA$J(N8rt9G9PwQ>OpF#`c<>c9H2h& zcuquSHTe=DBxqWru~Bo>d!EYj2ckJ$opJb{iHr*J>Q-f%|L-Z8cT2!uTd57rf8i8@ z@B7rI;=2T0I;TKklAj8)ej1t-#)Z1|O?U++AfiXS-^3OlEAU9pCwrEf zS#9g4WV~Na^tnw}_B&ehBRQP4J#l?a^uCERvFj`T`&G_4VbX1YC!~Q8{|4q>sqazJ`D5H^5Z_mmxVOlJw3g zCuXD{5TK0o2BNmeoe(*C*|4U_(eDUQ1N5yKU6DHnjv9uqOD0hS*9EaG=9T&#aN;hi zIsEa0dZu~3`I4BCUN#(oI9-=Tt`6dRMDB{n(bseqi4ALhyr3SqFp<;zkOAhWWTePx ze$0UWl;@QplJv_4q%53OvRBmlme>e=?dpKYX@22=ep+J;IO-Ao$^rhVf2QZIn6EYEt>0SJL6v6dSzy zacMiDB8?IHqhjji6A+}A1;Pu&sgvY}_?IEEgh21zQ;%ph$3ObtD<$6%Ax)_Oan=Yw zD1wVtWr{XIAjL@0S0dLGaeDcel+yf+13g8j_mt_<{FFm;#Dlc3UeHCq>p&H@K%kfZ zErIVu&IWN(-wHs#`+$FvmPCQ0v=1T|M;hRA{=}bpz%}Pj+~S&MkhgwB#!m=e5WXSM zfBXCc;U_{B!Y_p12s94#I{XWSmk6&AUL(9gc#H53fnJ+`hOi#lvFJ(?5E2oR5JC{J zgh|2>=#lS8GB1`eNhAW6D9LC9n%h_w=qG~JzZQfAQiAnR5{M9l5RA|Zp*Mm%LLUSV z1e#9dY~)BZ?`fXzLMTDljZliP2VpNl83Mg{T%?8RwHlE%2x}46A<%p0y%5|HXkqX` zpv8b*kZ*<18leq>ErK0_JwjWAb_neeIwH_`()iJEHHU12Kx+rSKP}Nhpfy7Wp@s`S zXtAKhL54s-D$^Um9ia~bJ!x2ikO`A!AxuP|MI#R(U&^Y5MdSSC_-3+KtD1Oi$Gs3qIG2(a2VPOKp2id>q;O(5JE6Q2tp`A7(zJ0NQ4N4 zQUt6w8ImK2&?-3ym3dP@g+2(r2z?Q-C(=)#({EJMFaFUB)9TlKY4*^xrrAN$mSzM^ zOPYqXz|o>a(=!_(2O$?>62fGJJOp}``xCt)OD~82g|HD}6T)VMEeP8XvJfUBWFzDt zN)cg2z+QHN1r|_LVlRj&_R0baEG)b0E}$p^ zvBa)e$AT^P5-c&n7E6pZ#;!^1E!7f3j3u$W-*bzg!t=bp_m7{Se3^UaOgVGroHJ+U z-n{{q0OTb*U=RsN$vcuaOa=@<3Sb1%022@i^aMHrtt0S=Ca@XU2w2eIIDkH& zL0)?i3eu_OIp91n4)=6)F$0(h%mO9>>3|VP1#*B~fK~wV=;YyV0knS7dYOQB^*|#1 zGK)T%G6)U#1m*+e#is$&0s3|RC8RTv;wS%h^MT306yQ@}HLwbx_q=Jz$^){1F~C@W zyni~730Q!UzzBdo8qoo0MU^_C0~MeK`~ZKTCEyHBe*tJoAkY2)I0t4g1N6O;Vw8CW ze2VMUz#3pJupZa|Yy$oOJq&4EpdAnad<1j@PJx#D9sZmKX!WI)+8G2FAOv`b{H91f zfk@DL0#QIOAR6cm^Z{akzCb^qKQI6o2n+%S1N1eRTp$nEbAY+PJYYV}e?Bh$0cZ`Q z&$lfAE(7%ahuHwFPXht^vV{%^1T6^A0tl_?%Zl_7SNa+tea}%?cIcOQg}_#TJ|%Mo z`4mY|*rCGxUEnpYzb7l6i$?Q-p}-)Z4GM2Zfo*^qc!PrTkRK1E;JPO0P5{L-F2F(L zuSB{EFylH3XaslwwSd}yGvEri0o8#Tz#EhwNn*JL%tpgEf#o3N0ONpYpbtPR{dtt3 zXn;N+a~pV$JcrU1Ee3g_wq4T1Uq zxpdjRlWUh3MWQzV$nE)>u+FIgflnN1y}xw`&i41VjMC6ryeYjB6vX1|WMQ zyIX>5ibXyJ$Xn@wM#!frBgR_cn)1l+c123lKzaGNrhFZs#eFb9Wh}VQrB28#b_1wF zU!*ZWAD}l73G@J{<7l84&=ZIPh(_1_fc~ZKX=NS=P^Sq1bsP(f00slYfT6$;n*ZUr zpvrMTJV3-$zyKrzi2yZ_1du|d07R$8iB2>#U;@$rl1@vEj_4#EncfiB50FRYym0La z#M1mMlo;bkiLq(GWMC379+(JB06qbzF)A|^m;#U_ z<#{LCEITL@5t#5hSymehP) zF92w?6d2IzRtxxG+L}9HvIV<*a3VYr9>bGsKPFQIw59=YniFT zxc(aW3fK$m0rmlhfP=sRU_TH8kX2AQxznS#rnZpcYmDN>|Cf~d(gQTWUjQA=KZ*Be zzyw?ct^lNPq}4wHr1h79AAs)xYTze;tm7_l3!u7ky~((yy4QhgzzyIga2vP-+yl}8 zs(+N`|2gmk_#60Dx_*H4H{f@`AGi zb%9u14+doCQ@SpdtA{djU-`J#)BICoI-miFzJL$l4HO`cIwAK<%uoZ90P3JV=rqdt z0Cl1RVgV{cbXq6KA<!P^11RqXztd0D$&hG?jrs5I|EYGaHO+s+()UAL2R$8DT&uFcpt;7TPgqe)OOJGf7BR98k`kEC6#@tn7gZ!Nw?Rc&)SYqN z3FruP0H%We5z=-5nPOX{5kPwh-H>(xx&qw++Og1JN)Ln-PoDBQH2*Y`2goFGkeSd{ zhqgbo?V+s@jfxl|yCyMD2YLduRU*cz!Bk)aK-(p%OYQVR8i#ZVunwTS3BWsMN%Kzy zXfHJs(BXP8(t!Z&tNd|Kwm$^den`nttpG@TNytkC^gsd-55xgFAQq6r`iHo_3v@x9 zJ4ibt{Shhc&2n4dhBj)sfD5j(k){9!U<{B2j0UX0C?FFs14bYfp!y^Q`e(v@ngmDW z%l8?`qxvHO3qW-U=p$Fy(A$tH7p80bk^*m;p!~5w4&V&>IHYrcp}0-}@^L*2m$ud4Qfhb&uokEQ>;rZK zG}0pAOJE032oM9CfQ`TgU_I~|uo>6_Yz3+VG$>+V8?YV7{Q`e>0-poa@GhVtuou_^ zd~I(FynpHRmBPqcaWV>QB|l2`NTSI9*J+{zsx_bt;G4r)3#L)vof_6knTmq2*1TjJe&1Yk zv%y6%JV@=Y4xmqib9Ec$uB5}EYA8{~9Delo-b?l}MUGY-5QfGYDR|d5ERmV*`L;Gp z!$#Y4{EsNy*>rpUy5!!qA{Y|0-1+e~tWL#1I2Ey|@o}2ub*ga~T zugFiMvFKYUK_c<=wO`SDWzbJ35ugqTR%`8awk%V8sv-UKXL`+Q)&6Oq_^ZJ@?4y!! z)R5O}RPziDZep_G-lvK?6bp%Ra72bMo|;B7y`{bmQgobq=$@LiPuuLD0w z`T3Rk1LP|`!DJn9;Zyz3PhV83w@7LcV$xLM-VrD%wWREbk~L9M9e!B<>$I5uQb}+n zwdo#%5;SIurH0#$@IaY6f4)3|DXGVO5#V5G75*6QYCSPKB>o*+E6uwY(0O`E&*k?d z^HM(7QVBloBjzEqE)P2J40N{!x^x+x55^S#=he0uBbCQpGG z4P?%D7b`rKPeCTVfBE9;ov~RiyNMj6MqN9+xAM4H;jYcnr5Q<~gZ`=Z)qn-thogi> z4RsQ&o)mFKqr8?aCh6mx6pm2sj>y5cS#CU0xVu*ePsG-M-WPigD?V{sl7v5R_(Y*) z+iUQlPZS!qw+7FDqKMSyLuu-wboGKBhd*`jP8C_Dt~P=~?bJE-s8f&rbB>l!ik$et zzZC9FN|i%uiR0<>)6-SUzCRFzl7SFJ5L|dIUIRQSKWqyY7$WGP*jBE&wx|!&8!uUL zX4S9DD=0LuM3{hG4k-99FSeasYtJ(`)|XK7kxd-_STp?0*S9KuS3+413Yg0C=+?iE zo?Vz*LfHxm29{U*w>}#?W%Gd&r9L`3020mG^f46{UF;lKucXoe7hd=`gm&D8$JT@r z-*Mr$e3=V(daCeZ_g%REQ%K{53-A6^p>og?*Y>WwZ4h%G;SHBZQ@!(r*OmOd<-42| zHIYNCwLnS+;OM0F_j86q&}^rI>jTsUS{v`*jPg81PV=lv({?|HXi!-JSSfB znWBL*4$Qx+6K&fBsRO;kwbNa>QUiutx#FjX;BkQ~FL;KRjUt~ZJe2#;8o9;gpVrRY z`jx@WMX?Gw*oWlF)tDP!S-+$@|Gg^Az}byQqfNf2E^ed-nU@> zY)zUeWoP&;nyCi~gZo_%KiCl^LPcxtU56jUT(aakdH6J*oW>P^h;kzpp>7d-AXgD72n{Qsx-QH`t;7 zwjSuehKD$BaU&bHiKtpL6m>~5=zo|8kN5|(AWgU1&nQX#Pp&w(>DAU(ucD+@t>KSd zm>2uQgP&@S){Od0J&C4|SL4yO?1yed8B7oL_tJxVS7Yvhkx&WJlVzjFCJr2z9Yy_x z!5amZH42idza3v%m3eBbE5(Vbzl_}qs=f0URP-ma4=t;r=m701)#Jr46dGmuo!Wcx z@D~bq&-z~CS~IS8xaP|u;{}0nL4^1*j0daBv|jwtb11v@AB9KsIFu&i-t=3ZE%c_} zVWwzK`hb7sFWfqK1xPUO)v}P>mN9-UO6q_I3wV$Pjdu>IN1-QP!xeUs;LW!+fOO5? zk_N;+c=J!b?kUMm)JShv?hpC1L?0g2qQu6W-nVgn!;3W(8y(}r3!B06E|TR*J+KKr zJcrtu<-=<-<_iT!0$EV%#KY29IvZJOZzy7)iF*XXi#e{Jw6mFb{$`z8}Ro$uj4; zEfA({@#WXl7|ua8hVzv#ck*NIxmOT1l5vl@THonZyebQ=p)G_lc4r!h19)m$INrr^ zT?0^{O{Dfi8wyV_@_vpUW8bsi;v!H&)S6&*m|YGiWB|Wzm{#-hBFvJFp`9Ug? z(OB%LxnI|p&xg1a3nc_)e1;ORT2`S6&!_p3eQFC=zWjALD#YrSnqb!^yls z_iD^Mw3$+K3!U;l3LIA0i7DW0)d7&gB~Zv$O?>mk@_*f3O_HeKA#OF{u}UUHu1lKo z*KUk{lqT4o)Roe=ndp(ft^8Z#?olUC5tE{ygQ0)zf&fmIhvc*52L5WsjaYg_lM>`1 zH~9ulk~^B$BcyOgXd4eSNplK4h-$vj3&WKCWc3!}oE)m%`tK2ubH7DFC=3F8J9$pz zWl?e|Y+(zY?}--PW9Y4Z=mLrXr3{pt&TYxtLP7Yh z=ZX@Wl`M>vwj(yDC4UTetGv=uIAqA1wQ5JdSL4o5o07<675YZSv*BE{msFx8+#;*} zv2*{}@2I4x0e3)gf{dIm`Ks4!U%FqUkjs|E{U6j%SuEAAd3Ql$U;hEuQCkXZB?0k{ z%}Ob#q>yhV#MIo$7gBuB1F@=VZc&w}p(sIjwKz$;=49V&zj9PQ`jRYEa*)x>QG&*D zKV|GERa$9RphO7NT!TG5DA)?-J&T@S)DX~~s)msIEN zIOP0txRSZn&V!x6o8`@GlB?_YDC)T&nNW(=cY#8|-|$T}eII#`qL2hjH3d%>0{A|R zRQVhw;0y8`n-3aV>pKv^6R7R7~cm@oD!a6Te%!9lb=2?a1KdArm8YS4bsZi?+B#&?2(l_2k{ zX^XwGFYOTrEer|j=Tw=wRezLy-_Gqs5Lz(H2Gcb7&|pTR3wU7qpb*%Er_qI$XvXsSRRUzp0)4Q zuUF5R^T@`fRd06C!V1i#5-osG_k0C&aTmBmh1#fa|JNl;V*CzAqJoBdE10)OlHNpz z1a`3=y+R85SA`?lhO*>jd4z%m@wN`kBP9xJFzH95BkN+Cc&1b+>973tw>*()$`x5~ zsWArshcQY6v)8JF`Qi#JxNKJ}NLmtFX?eVJjV9zyE77&oG=v;%=ZM1)I?!0^TJ*ce zq!^`y`P=pdgmcyT4h#cKP`gUzYTI6BOEgnHQa@nKLDlgM!@` zdA|FgP#E_3n{k$c?@v*vj?h9Kz+<1{f1iDTF^AkNozZBprP~$rZI?Z=eJFsUGX$9a zj&QNrz`5~b4lP?bjw#k6hm>iA+p14&AvirCle_aI&h$wt_R>uAC%J0(u+r9d|_TDf5|3X)O+)mu? zjN2EJ*ZR<8T683bQVz#u*AT*=QZ?S^>79F&6LvvTxTN%fHPLZY)}LSeaJAjO9PmK) z77%LJy)(as4T7+4Dwmhx%EYizKBAGgM{;l?2P4udEpKw%Ee5MDU2n6?eRMx7yt^Ak z7ZiU4@u-$esU3mGK()Y5^+pH6JD&5?OH^p(9#AMK_N!SruKt|Qe-{`Hpmp>}XP#FF zL2(FPHWH6rJZp3nt;swzEn-K?r~yJV6o}%OS=cywJ0qU*?#lOL-}QE9_dd%~xc-*) zQ95I)-iia$=;l|vZI$bwRSMHWd8jiENO@QOk1NygeAmxH(e$%!{1#GAb6ML` z;lxg4D7s8t5cV_SJ;Y^Ty~XwF(;DLxQm?R*0ie+Oa`xw8o1c%|vqKUIgk|W#3vq7N zJP#$vLoD0+{0Wb}N~bVzW@KUS*X1YcGN1a8rUHgeuA@G?GraesN3?^J&K7arSx^hB ze|hJfcmNs6&!U9e;Ye|=D*m!SYg$xTO=OwBuEj#NWwtMD?aZclJ&p(Lj&Ezfc+qH` zqfiTdm7II*Uddk-f#i_wW5} zl+J1AF|;n8(bx^>&HFr8B$jQ(!pbRG@qaJDgXm=NeVf}H!=oEP>tvgg4h8v+hRnld zUyK;OY%pKmdv0WPZ}6qzdDWP=vTt88{#l)pnUVE+NIjyc18CKY>&ur@gT}smS0k*w zI}lotK7}{`B=$rvkLhm@7-Y+ncasta+Vb7Y`2M1v-LK|dx9a#t8gxo}hS`=!CGWo2 z03J@;7$ZFhKgjOy(kN7|yvg=9YDt&!{)F5rm71p`=p>3Gw>cATf@Isxbub1&_q zadx{t*tvS>@9QI&g1i@;sGYnakT(i4`~QVAxr0rEcuSl$ zl^k10qn7uN(g>u1iQ9A~j)Qm#{wP}y7AN=c(#z*Q+5OojVG0Flb|1`FwnV${?^EP6 ziuX5(bT%RHlU-uaEIETlla8%D;C+TdUag=r^5$8Vw|G)5i$ETeBnoAZA>xTu!H(%O z0;*N4g@<`k$R_Uw6+?Mm0JxME9p*fgZ=uCUH~^OvLfpT8c)*WE69>mQJQ~Vh`=bqM zM=34)ZWKGguYC}?3lBRGf(g4*sek45p<=Ys=4j=nF_n*ffdSJ2G9q!5+(xa-!L7eK zncuEZY}6wCJoLSXXQ&)ry_P3NOB$MV#_tJv(Fb0|96eYd~jSpJ$?k^7ay z4cTtxHC#H1(^k-l@y+BZl?=Nk-kFWjOGh^4pU;+K8uBw1CLiaOd8#BIhL!)gMP^a5 zJYMJqX-Os{91SX;foY0$qH~Ps6##s0lC?vPdB9L?FO{kJYpt3`34GY8?dN} zF_ycN8g-pf*V6CIz+VPfbNO6%)^MRa^8j2Ogr^v(2|U^zrt5)RJ|2Ix;aJvb`{4N7 zfO_p#&iDt-N*Z_y6bkoV#@YST{!N|vpwJOB1}bY!Ioje`{=yr+c?o(Sw=`o5gS;S9`Vz2=$2Xx77JRe7LI;zis} zy2>sn;fcC?mgwEP%uhL7QX(#u`-kAn3zO*KtpSuE-P}nCNLW&+|2l$sfYfbk{z2^Ig zt%dMoADbv?yA4bCv+AIpcla%+6NTVS8298Xc}=Ar;Lo8(~NR)nWR@>>?5 z;9P+^N(T!huFWf5=N?_=yxNx;Y5$1MXMjSh`s3F-2mbcv;Eh1Luk;a(TH9zS!KWfFSkR!{3h{; z0(e0w5FuV!Z#B`=pR(U-5?&s$b1;hn%s4spdA$vzv8TbKHKC5PM9KN}$F9APW#Vx= z9i>ofx;R66mPK#ZchF|zTs|y}RjG%qt)0PU9z}zSJ>RTlDHy_x#o(k z)<>)4YS&~LS0mMsL*ZPu36!DI1`FpK6UuM?41;C+mQYT39nK* zqP4PK!V=Z&Y_Ln;LD!x*xbQY@Se4ulMFhb^m&y`R`4pNf5(HC-RyN!5T1fS@(L%6} zv0$>w>_@8(E3YF#upiC^SP&@AW**TROO|76ti)|Cd=_p}$`%U^rfdocY>YVpeB*~q z+Pn9=bj&^Eq&RF5m+}u^e9MtE!C@q~v|_GdP{9v}g+js{m04Yol2qLu)%m_wI5z&j za93u>Li1&IEa+M(zCSD^Yq<+Fwgxold$;B@S3Pg`ITMdez^wSrpgS+dn_h|^_=pay zZm%+4(jY~|tbX`n1r%TS_Ygghj-JrIS*1?U<7qhjiJ(5ucndTd=mb|mAyVl0TS2py zwa2LqLk=+|fBz$KYuk8d*JkuYfZkrg+Y~Q4uwXv8Jpz~r{0Xd!3bm<;hpiS5bC_HU z1>qAYPWf=ci2{GZ$9BXE84pmA{O6#URoO3f)37)}dj;;6W{6yExcS#Ff9`r5AT~*S zL;p^7gs=C`6ieLtyWxSlV^1YXqC<&0nY^$AR-=cR{7wh91Rp1T(~;Fx`ivGU4Cqr} z_xg{2D6S*@hO8}Fyr2`#WpcB`!*##;I)2k7g5FsqR@I&GdW!gD%q1EQ*)C0Q9!0|C zk;N?x%j!NtIf^#W^?=@@I(Nx-UKKa|_IjZOfwB;7Q_R|Lz^UH)2RU6qfdb(Tygpr+ zR$JzyVK^YX&^|`^#bjP__Gb|Xdb3YZPb0bv(-^+L3l_{WUyBg>EVETXIctyQ5nW-? zIQej`Ks$V{d#Z4D^cgFzbOB@e@<_<|Gu+esjEQJ*Cs5V5Dms^9yxn8@EHt3?&K4IL zhjzwkd%X822&9KL+BaGwbjysSiP?nB-KpK4aNlB#}j?w40bV}I2O zRfVy4%i*VcAjTSy!RqJGWz%U9|O)`iPh)PTJ{vUs)E-`uip*ICMiF zgS#=Mdk;{_X$7=f(L34%{_ZMk#FgSfmWI%>fwQwORu!<=iVJf zX@UbWBa`^8ZtxT0KGl^s>(1&a7oa%#OUGrmuS|5f8z}XQQG0yCv%AA)V!Old-N7H~ zVjFU_S3ePDIoYAv@}8@Akkuoyr+BK#WKo8#>vtVKW^VT$Qs>a2zb5n7sLM{`e=G*y z^LAg)I-}w5r*N;%$oypr5A6&Nr@C?BJ-*^8{1eQ@+*$QE(Ee4+6%LjGE*E$$C}&Lr_Ve)4d=wdG-HR`jpz5m zSofhsEi{-gx^sN>5gt6$@uM07WOyum4<+ttd^ z;s~#&@1K7l^5Btpob*$JRexx5S=BD^@Fa|aLi`P1T==tlX!pGLcOCE3^AkmWD$|F1 zz)Y7u%*Q@H!NN!OVFteLOB~>v_OPb-MmgWZ+Pg*Q60Ew!#4JBNbXS?o)-;{bFhs=ds_o$j(qJZ}aL9UkadCw^uIYrt0&F$bPn#A@@;_p)Jp^==kf z23oUB&6>Feyz~(}oo-~G!*w5H3E&0sR9Y{`aHLz>Q-nqVGfQW?@IGfkHspUkJnu#Q~UpLz1Efvg7qC0s8p)OB_KWHA0$0#a$!5atS51@lfrSXaJq z2s_Fyj71aql&T#D(GLLAxXH*gf1lL(z$L9 ztH-Z?#_I6bpE2)hwsfn(l%yJENJvi>1$zG~3jAD%H$yYFK@5)C;uT2eerA>FHUjL{i#xUh6aPpwD5AtBFIj#V6}ALxOtU%Yh=JO%HxB z2TVSShazu{WmEZ(r7VQ|=CZcDZybh~8OPT02Ul1X-h3$w5X(7_VD)+22th#u8BHB*0Sq$-JQE{QON?v6=hA{DC){eiNiA7GB(0OZF{oGO$ zYSWL*(BnCwH9@bpr0K0mqP*e_*7yvYAUeG%(_l55(hys~*b_v$RiC6Et;$F@7=nN6`dnoUrdG-{D#U5^i6$9nSK6Y#7zYyR!M?`RS#sQ5Di#RU(X=k30is-naltD%il(1?;-meycpzLMdr7^gBLP&wxXcj9>O zHP9D0i%Q&aHMIMNo;7fi^abyL>G3KAq`5r_E_rMs^YxNQf)z?rG};1@i>&fxiOjpX z&|!ihF;VPU6uel#q)X4R>WrkVP-8vUo8XH>)LPLAPnf_ui{tUkf$PM`X7N4w*yujW zWnK8$jjU49jYRepgBJP=T39s&QtX++ocSRWJVd(`R=tKzVp06UC_ianUiG0@)@GRy8hK{oVeX3zEKA?thQ*&sXSKLh4~>15&RTMF28-cC zZLF5?l9|QEEP`Io8I2XFu?0(jmgmoaznPbgX%~!Ua5}5w0NoeZ{msU@%0&d~Lkp{m z!2}D`ZB|yNsNqN!%J|nASiQA;q#kVv1qC}gV`BbqhmHZeRx+dsY7387kH?x>b&etq z{EC@1DB(+}D#)lHh55Yg?Z*`6?-FOli5(P$-m@}VGgR?9tkH8OW8h9E){iF_V%a*L z%IZ4@VZ)1MUXWU#zrTNgHkAL9%H~xRy+MHy9z7_H*;uHC-`)ywolIj5?X_VVF33i9 z1CBgA75U@~g#4+gh~XreHOs){W3aA#h=JAQ3p3e#nIz=4G%$~%v7=bi3Z*3D%2y<@ z+C>k>vMdGvBOVLvnF-8$;Y8+IYZT%USe(JAS3!s2KBZ-H8oS1$^AU2~{t|o&*2DEs zuT#@mqk59{m0AK4<5Ys{NYk0P?gAw9%PcHc8)mZ&Tr-R94gZ5|2P#j-%Mr^yavZ4_L|K0 z@m7;q3nyA-EwFxF5=4%aCeJ_+|8X4i6z)FCr72vAS8N2UwU{gvo6sU;l~T2SwCE%$ zSo9ml9ExtQWGfXse~B-ilhRz_SN3U|tWw8UvnZ-viN9IH7Vz!sn3s>irh4mpREZ{mAw5*nl3~@WtXQyUD(mr>^~}br zu7}zjUC(M`6oLHedMsJPwy;*@EqohD(F#)X*bqJ=En_5GkMGZf(guQm~i6}uR5Ka^Vt!0>ynMRmd^wRh72nS51GvYD~ z#)Q%t2qkPh>Pt3|TTRTf2F^+SRDSrYqT^AnOJzQ->46I}DN*6rNrR0m?R9MN&_lmC zgC$T?>N;!`lq(}W8B*5-YXzY#+>8GuTBzX08@xkBqwn0SuofX!4S??|wVM-mN7&re zmD=z!k48oFXq1)~K>DE`bkC5UuD1sAT6?hjo3#sJm)9;<*$MoGp*-;!rouTZFD_yo zc(4t6xUvYUO*=*?CPwPZ>+gbn4%>xzOv`;HBLu*@fV#pH9n{6IpagG;#^E=2flKN^ zt{^N^#HYBQd%GQ#{q(4BVB%GdK+O?QIq*~8ATVlogn3p95?As3Bg{20K`(4Du%s4S^Tstk+R(ZJpAOwqL@Ma0cah&LsrRTQ9S*yzK?nwn+Oe z9KNWN$)}+Ny6dcqyP!?955fwew_1!Ca=OZBz}}fQZ@*q=+lw?eS*pUG9x1H6#h&xx zuOaVUx7o6~l0nfnObU9*fg+3+e7gF>d_Bygj9l1efapE=s5@Ah;!@GW^*b!tv8#9% zWEcIM_qq!O@Vv*WJ1&wkk3Z+*@3PMGx_UQtd@kkLy(m?%D}DYM|Ds=T%{|r@@5qn5 H$N2vM#Oh7o From a5285c784b9c2c123279a58c86619a8a823575d0 Mon Sep 17 00:00:00 2001 From: nlok5923 Date: Sun, 8 Jun 2025 13:02:52 +0530 Subject: [PATCH 3/7] Feat: Add confidential transfer and withdraw action --- .../src/actions/confidentialTransferAction.ts | 139 ++++++++++++++++ agentkit-core/src/actions/index.ts | 2 + .../src/actions/withdrawTokenAction.ts | 149 ++++++++++++++++++ 3 files changed, 290 insertions(+) diff --git a/agentkit-core/src/actions/confidentialTransferAction.ts b/agentkit-core/src/actions/confidentialTransferAction.ts index e69de29..041534b 100644 --- a/agentkit-core/src/actions/confidentialTransferAction.ts +++ b/agentkit-core/src/actions/confidentialTransferAction.ts @@ -0,0 +1,139 @@ +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 { + let confidentialTransferTxn: Transaction; + const depositTokenContractAddress = getDepositTokenContractAddress( + args.tokenTicker.toUpperCase(), + ); + const tokenAddress = getTokenAddress(args.tokenTicker.toUpperCase()); + 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); + confidentialTransferTxn = { + 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/index.ts b/agentkit-core/src/actions/index.ts index 1f52231..3f25388 100644 --- a/agentkit-core/src/actions/index.ts +++ b/agentkit-core/src/actions/index.ts @@ -1,5 +1,6 @@ import { GetBalanceAction } from "./getBalanceAction"; import { SmartTransferAction } from "./smartTransferAction"; +import { SmartConfidentialTransferAction } from "./confidentialTransferAction"; import { GetTokenDetailsAction } from "./getTokenDetailsAction"; import { CheckTransactionAction } from "./checkTransactionAction"; import { SmartDepositAction } from "./depositTokenAction"; @@ -14,6 +15,7 @@ export function getAllAgentkitActions(): AgentkitAction[] { new GetTokenDetailsAction(), new CheckTransactionAction(), new SmartTransferAction(), + new SmartConfidentialTransferAction(), new SmartSwapAction(), new SmartDepositAction(), ]; diff --git a/agentkit-core/src/actions/withdrawTokenAction.ts b/agentkit-core/src/actions/withdrawTokenAction.ts index e69de29..ad168a7 100644 --- a/agentkit-core/src/actions/withdrawTokenAction.ts +++ b/agentkit-core/src/actions/withdrawTokenAction.ts @@ -0,0 +1,149 @@ +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 deposit +- 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 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: +- "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 { + try { + let withdrawalApprovalTxn: Transaction, withdrawalTokenTxn: Transaction; + const depositTokenContractAddress = getDepositTokenContractAddress( + args.tokenTicker.toUpperCase(), + ); + const tokenAddress = getTokenAddress(args.tokenTicker.toUpperCase()); + 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); + withdrawalApprovalTxn = { + to: withdrawTxn[0].to as `0x${string}`, + data: withdrawTxn[0].data, + value: 0n, // No native currency value for token transfers + } + + withdrawalTokenTxn = { + 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; +} From 9cea7f3dbf8e6c2e6d2e1302cda640417e621b02 Mon Sep 17 00:00:00 2001 From: nlok5923 Date: Mon, 9 Jun 2025 20:41:40 +0530 Subject: [PATCH 4/7] feat: enable withdrawal action --- .../src/actions/confidentialTransferAction.ts | 141 +++---- .../getConfidentialTransferBalanceAction.ts | 345 +++++++++--------- agentkit-core/src/actions/index.ts | 2 + .../src/actions/withdrawTokenAction.ts | 163 +++++---- agentkit-demo/bun.lockb | Bin 0 -> 40744 bytes 5 files changed, 339 insertions(+), 312 deletions(-) create mode 100755 agentkit-demo/bun.lockb diff --git a/agentkit-core/src/actions/confidentialTransferAction.ts b/agentkit-core/src/actions/confidentialTransferAction.ts index 041534b..b05d61b 100644 --- a/agentkit-core/src/actions/confidentialTransferAction.ts +++ b/agentkit-core/src/actions/confidentialTransferAction.ts @@ -1,13 +1,16 @@ import { z } from "zod"; import { ZeroXgaslessSmartAccount, Transaction } from "@0xgasless/smart-account"; import { parseUnits } from "viem"; -import { - depositContractMappings, - tokenMappings, -} from "../constants"; +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'; +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. @@ -32,17 +35,17 @@ Important notes: `; 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}`); - } -} + 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 -} + 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 @@ -52,8 +55,8 @@ const DECIMALS = 6; // USDC has 6 decimals and we've enabled deposit for USDC on * @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}`; + const tokenDepositContractAddress = depositContractMappings["43114"][ticker]; + return tokenDepositContractAddress as `0x${string}`; }; /** @@ -61,28 +64,26 @@ const getDepositTokenContractAddress = (ticker: string): `0x${string}` => { * @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}`; + 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", - ); + .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. @@ -92,48 +93,54 @@ export const SmartConfidentialTransferInput = z * @returns A message containing the transfer details. */ export async function smartConfidentialTransfer( - wallet: ZeroXgaslessSmartAccount, - args: z.infer, + wallet: ZeroXgaslessSmartAccount, + args: z.infer, ): Promise { - try { - let confidentialTransferTxn: Transaction; - const depositTokenContractAddress = getDepositTokenContractAddress( - args.tokenTicker.toUpperCase(), - ); - const tokenAddress = getTokenAddress(args.tokenTicker.toUpperCase()); - 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); - confidentialTransferTxn = { - to: transferTokenTxn.to as `0x${string}`, - data: transferTokenTxn.data, - value: 0n, // No native currency value for token transfers - } - const confidentialTransferResponse = await sendTransaction(wallet, confidentialTransferTxn); + try { + let confidentialTransferTxn: Transaction; + const depositTokenContractAddress = getDepositTokenContractAddress( + args.tokenTicker.toUpperCase(), + ); + const tokenAddress = getTokenAddress(args.tokenTicker.toUpperCase()); + 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, + ); + confidentialTransferTxn = { + 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"}`; - } + 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 + 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}`; - } + } 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; +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/getConfidentialTransferBalanceAction.ts b/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts index 64f7afa..54469fd 100644 --- a/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts +++ b/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts @@ -3,7 +3,13 @@ import { BalancePayload, ZeroXgaslessSmartAccount } from "@0xgasless/smart-accou 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'; +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. @@ -13,6 +19,11 @@ You can check balances in three ways: 2. By token ticker symbols (e.g., "ETH", "USDC", "USDT", "WETH", etc.) 3. 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 deposited amounts for confidential transfer or 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. @@ -22,60 +33,62 @@ Note: This action works on supported networks only Avalanche. `; export const RPC_URL = "https://1rpc.io/avax/c"; -export const AVALANCHE_CHAIN_ID = 43114; +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}`); - } -} + 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; -} + 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"); + .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 @@ -85,28 +98,28 @@ export const GetConfidentialBalanceInput = z * @returns Array of token addresses */ async function resolveTokenSymbols( - wallet: ZeroXgaslessSmartAccount, - symbols: string[], + 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 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}`); } + } - 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; + return resolvedAddresses; } /** @@ -117,119 +130,119 @@ async function resolveTokenSymbols( * @returns A message containing the balance information. */ export async function getConfidentialBalance( - wallet: ZeroXgaslessSmartAccount, - args: z.infer, + wallet: ZeroXgaslessSmartAccount, + args: z.infer, ): Promise { - try { - let tokenAddresses: `0x${string}`[] = []; - const smartAccount = await wallet.getAddress(); - const chainId = wallet.rpcProvider.chain?.id; - const chainEnum = getChainEnum(chainId || 43114); // Default to Avalanche C-Chain if chainId is not set - const tokenEnum = getTokenEnum(); // Currently only USDC is supported for confidential transfers + try { + let tokenAddresses: `0x${string}`[] = []; + const smartAccount = await wallet.getAddress(); + const chainId = wallet.rpcProvider.chain?.id; + const chainEnum = getChainEnum(chainId || 43114); // Default to Avalanche C-Chain if chainId is not set + const tokenEnum = getTokenEnum(); // Currently only USDC is supported for confidential transfers + + // 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]; + } + } - // If no specific tokens requested, get all tokens from tokenMappings for the current chain + // 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) + (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]; + 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; } + } } - // Remove duplicates - tokenAddresses = [...new Set(tokenAddresses)]; - const confidentialTokenBalance = getConfidentialTokenBalance(smartAccount); - let balances: BalancePayload[] = []; - balances.push(await confidentialTokenBalance); + return `${displayName}: ${balance.formattedAmount}`; + }); - if (!balances) { - return "Error getting balance: No balance information returned from the provider"; - } + // Sort balances alphabetically by token name for better readability + balanceStrings.sort(); - if (balances.length === 0) { - return "No balances found for the requested tokens"; - } + const responseTitle = + tokenAddresses.length > 0 && !args.tokenAddresses?.length && !args.tokenSymbols?.length + ? "All Token Balances:" + : "Balances:"; - // 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)}`; + 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 GetBalanceAction implements AgentkitAction { - public name = "get_confidential_balance"; - public description = GET_CONFIDETIAL_BALANCE_PROMPT; - public argsSchema = GetConfidentialBalanceInput; - public func = getConfidentialBalance; - public smartAccountRequired = true; + 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 3f25388..656309a 100644 --- a/agentkit-core/src/actions/index.ts +++ b/agentkit-core/src/actions/index.ts @@ -7,6 +7,7 @@ import { SmartDepositAction } from "./depositTokenAction"; import { SmartSwapAction } from "./smartSwapAction"; import { AgentkitAction, ActionSchemaAny } from "../agentkit"; import { GetAddressAction } from "./getAddressAction"; +import { SmartWithdrawTokenAction } from './withdrawTokenAction'; export function getAllAgentkitActions(): AgentkitAction[] { return [ @@ -18,6 +19,7 @@ export function getAllAgentkitActions(): AgentkitAction[] { new SmartConfidentialTransferAction(), new SmartSwapAction(), new SmartDepositAction(), + new SmartWithdrawTokenAction(), ]; } diff --git a/agentkit-core/src/actions/withdrawTokenAction.ts b/agentkit-core/src/actions/withdrawTokenAction.ts index ad168a7..c2a32df 100644 --- a/agentkit-core/src/actions/withdrawTokenAction.ts +++ b/agentkit-core/src/actions/withdrawTokenAction.ts @@ -1,13 +1,16 @@ import { z } from "zod"; import { ZeroXgaslessSmartAccount, Transaction } from "@0xgasless/smart-account"; import { parseUnits } from "viem"; -import { - depositContractMappings, - tokenMappings, -} from "../constants"; +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'; +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. @@ -31,17 +34,17 @@ Important notes: `; 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}`); - } -} + 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 -} + 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 @@ -51,8 +54,8 @@ const DECIMALS = 6; // USDC has 6 decimals and we've enabled deposit for USDC on * @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}`; + const tokenDepositContractAddress = depositContractMappings["43114"][ticker]; + return tokenDepositContractAddress as `0x${string}`; }; /** @@ -60,28 +63,26 @@ const getDepositTokenContractAddress = (ticker: string): `0x${string}` => { * @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}`; + 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", - ); + .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. @@ -91,59 +92,63 @@ export const SmartWithdrawalTokenInput = z * @returns A message containing the transfer details. */ export async function smartWithdrawAction( - wallet: ZeroXgaslessSmartAccount, - args: z.infer, + wallet: ZeroXgaslessSmartAccount, + args: z.infer, ): Promise { - try { - let withdrawalApprovalTxn: Transaction, withdrawalTokenTxn: Transaction; - const depositTokenContractAddress = getDepositTokenContractAddress( - args.tokenTicker.toUpperCase(), - ); - const tokenAddress = getTokenAddress(args.tokenTicker.toUpperCase()); - 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); - withdrawalApprovalTxn = { - to: withdrawTxn[0].to as `0x${string}`, - data: withdrawTxn[0].data, - value: 0n, // No native currency value for token transfers - } - - withdrawalTokenTxn = { - 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}`; + try { + let withdrawalApprovalTxn: Transaction, withdrawalTokenTxn: Transaction; + const depositTokenContractAddress = getDepositTokenContractAddress( + args.tokenTicker.toUpperCase(), + ); + const tokenAddress = getTokenAddress(args.tokenTicker.toUpperCase()); + 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, + ); + withdrawalApprovalTxn = { + to: withdrawTxn[0].to as `0x${string}`, + data: withdrawTxn[0].data, + value: 0n, // No native currency value for token transfers + }; + + withdrawalTokenTxn = { + 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; + public name = "smart_token_withdrawal"; + public description = SMART_WITHDRAW_TOKEN_PROMPT; + public argsSchema = SmartWithdrawalTokenInput; + public func = smartWithdrawAction; + public smartAccountRequired = true; } diff --git a/agentkit-demo/bun.lockb b/agentkit-demo/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..4c614d97b03d67678b239bf050a554fed20aacae GIT binary patch literal 40744 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 Date: Thu, 12 Jun 2025 12:46:45 +0530 Subject: [PATCH 5/7] fix: eusdc addresses --- agentkit-core/src/constants.ts | 4 ++-- agentkit-demo/bun.lockb | Bin 40744 -> 40744 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/agentkit-core/src/constants.ts b/agentkit-core/src/constants.ts index 627f48e..0f5ea69 100644 --- a/agentkit-core/src/constants.ts +++ b/agentkit-core/src/constants.ts @@ -45,7 +45,7 @@ export const tokenMappings: Record> = { export const eTokenMappings: Record> = { 43114: { - USDC: "0xecbe4f05955f232f4af30636845fedb9ba173abb", + USDC: "0x7cd958f1c47083d5911ad71fd32b856a8c77ab89", }, }; @@ -380,7 +380,7 @@ export const Permit2Abi = [ export const depositContractMappings: Record> = { 43114: { - USDC: "0xed7bf74200f4f1105a6cd606f66d4db500a906fb", + USDC: "0x85ea5a1ae0ebbcbd015e078a08fa9cc0d00bdc93", }, }; diff --git a/agentkit-demo/bun.lockb b/agentkit-demo/bun.lockb index 4c614d97b03d67678b239bf050a554fed20aacae..ab0171ae177f3c3acd04c6ad60d648d6ac00f610 100755 GIT binary patch delta 659 zcmW;ADQv<307l_J2r~bz?_&ckJrUG!t9r$P^NZL?SWGDk~dQvxEd$S&2j< z$y8-!GyZ43yu5Kz9w+7BpJu7#2hFdQ89JNl5OZ|5bRsO!+t!J(x})yk6l=RWT}-fU z>hv(h#-2_eXK3u}3~-KSOJ|4+v<`GexJ3I5OoRwyhIjhR(H4h&j4#od^r`ZggU- z-l{t|#oC=t7Za@C>+~?i#)D2DXJ|M&1DvDzs58U`T2DG7T%!G~6JUnUi%y6+y01DB Z7U;dL&ZPBeRQ&I?iogD`G5LFMyZ>cBxf1{Y delta 657 zcmW;AD@+0b0Ecm9>@4nPA`%f_r}#J(^~Bft+|8gzV!+Z3#VxA>9jG% zlBLtZ8J72Tx|m?)K&OXuv}!tiT%diZGr%P}M>+wf=pO5Yn4x!~6Jd_NtusdBRNcZU znrAv~jIngC)4>^*>pERbuyUc(!#P@)I(=NAeWf$NB|45yfGN7yIw5B0HFP4((ZA6d zqj9Tl;S|j~oi@f;y4UI849gEXT}-gz>hy4q)}u}z7id4}3~-6gvrd31x-U8*X6U`@ bM3|%h)|}KnH;coswc>F7V`K9B-thhabvn4I From cdf0452e06859e5d00239b02e5264cec5b38fe15 Mon Sep 17 00:00:00 2001 From: Archisman Das Date: Thu, 12 Jun 2025 21:12:11 +0530 Subject: [PATCH 6/7] feat: add private balance checks and withdrawal --- agentkit-core/src/actions/getBalanceAction.ts | 1 + .../actions/getConfidentialTransferBalanceAction.ts | 10 +++++----- agentkit-core/src/actions/index.ts | 2 ++ agentkit-core/src/actions/withdrawTokenAction.ts | 7 +++++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/agentkit-core/src/actions/getBalanceAction.ts b/agentkit-core/src/actions/getBalanceAction.ts index a4721aa..a0dc3f8 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 index 54469fd..43e3ed7 100644 --- a/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts +++ b/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts @@ -15,9 +15,9 @@ 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 three ways: -2. By token ticker symbols (e.g., "ETH", "USDC", "USDT", "WETH", etc.) -3. By token contract addresses (e.g., "0x...") +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" @@ -25,7 +25,7 @@ EXAMPLES: - "Check my private balance for USDC" USAGE GUIDANCE: -- When a user asks to check deposited amounts for confidential transfer or his confidential balance, use this tool immediately without asking for confirmation +- 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 @@ -239,7 +239,7 @@ export async function getConfidentialBalance( /** * Get wallet balance action. */ -export class GetBalanceAction implements AgentkitAction { +export class GetConfidentialBalanceAction implements AgentkitAction { public name = "get_confidential_balance"; public description = GET_CONFIDETIAL_BALANCE_PROMPT; public argsSchema = GetConfidentialBalanceInput; diff --git a/agentkit-core/src/actions/index.ts b/agentkit-core/src/actions/index.ts index 656309a..3e39428 100644 --- a/agentkit-core/src/actions/index.ts +++ b/agentkit-core/src/actions/index.ts @@ -8,6 +8,7 @@ import { SmartSwapAction } from "./smartSwapAction"; import { AgentkitAction, ActionSchemaAny } from "../agentkit"; import { GetAddressAction } from "./getAddressAction"; import { SmartWithdrawTokenAction } from './withdrawTokenAction'; +import { GetConfidentialBalanceAction } from "./getConfidentialTransferBalanceAction"; export function getAllAgentkitActions(): AgentkitAction[] { return [ @@ -20,6 +21,7 @@ export function getAllAgentkitActions(): AgentkitAction[] { new SmartSwapAction(), new SmartDepositAction(), new SmartWithdrawTokenAction(), + new GetConfidentialBalanceAction() ]; } diff --git a/agentkit-core/src/actions/withdrawTokenAction.ts b/agentkit-core/src/actions/withdrawTokenAction.ts index c2a32df..93ad1e0 100644 --- a/agentkit-core/src/actions/withdrawTokenAction.ts +++ b/agentkit-core/src/actions/withdrawTokenAction.ts @@ -16,12 +16,12 @@ 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 deposit +- 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 deposit in the input token's units +- 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 @@ -95,6 +95,9 @@ export async function smartWithdrawAction( wallet: ZeroXgaslessSmartAccount, args: z.infer, ): Promise { + console.log( + `Smart Withdrawal Action: ${args.amount} ${args.tokenTicker} to ${args.destinationAddress}`, + ); try { let withdrawalApprovalTxn: Transaction, withdrawalTokenTxn: Transaction; const depositTokenContractAddress = getDepositTokenContractAddress( From 7b8816dee0ea77766abc761d5de02e1a32f06d37 Mon Sep 17 00:00:00 2001 From: nlok5923 Date: Fri, 13 Jun 2025 22:05:49 +0530 Subject: [PATCH 7/7] Fix: lints and conflicts --- .../src/actions/confidentialTransferAction.ts | 7 +------ .../src/actions/depositTokenAction.ts | 5 ++--- .../getConfidentialTransferBalanceAction.ts | 6 +++--- agentkit-core/src/actions/index.ts | 2 +- .../src/actions/withdrawTokenAction.ts | 9 ++------- bun.lockb | Bin 0 -> 226928 bytes 6 files changed, 9 insertions(+), 20 deletions(-) create mode 100755 bun.lockb diff --git a/agentkit-core/src/actions/confidentialTransferAction.ts b/agentkit-core/src/actions/confidentialTransferAction.ts index b05d61b..4b7b6ac 100644 --- a/agentkit-core/src/actions/confidentialTransferAction.ts +++ b/agentkit-core/src/actions/confidentialTransferAction.ts @@ -97,11 +97,6 @@ export async function smartConfidentialTransfer( args: z.infer, ): Promise { try { - let confidentialTransferTxn: Transaction; - const depositTokenContractAddress = getDepositTokenContractAddress( - args.tokenTicker.toUpperCase(), - ); - const tokenAddress = getTokenAddress(args.tokenTicker.toUpperCase()); const tokenEnum = getTokenEnum(); const chainEnum = getChainEnum(wallet.rpcProvider.chain?.id || 43114); // Default to Avalanche C-Chain if chainId is not set const tokenConfig: TokenConfig = { @@ -114,7 +109,7 @@ export async function smartConfidentialTransfer( parseUnits(args.amount, DECIMALS as number), PlaintextType.uint64, ); - confidentialTransferTxn = { + let confidentialTransferTxn: Transaction = { to: transferTokenTxn.to as `0x${string}`, data: transferTokenTxn.data, value: 0n, // No native currency value for token transfers diff --git a/agentkit-core/src/actions/depositTokenAction.ts b/agentkit-core/src/actions/depositTokenAction.ts index b2dd8fd..9c4a763 100644 --- a/agentkit-core/src/actions/depositTokenAction.ts +++ b/agentkit-core/src/actions/depositTokenAction.ts @@ -81,7 +81,6 @@ export async function smartDeposit( args: z.infer, ): Promise { try { - let approvalTxn: Transaction, depositAndWrapTxn: Transaction; const smartAccountAddress = (await wallet.getAccountAddress()) as `0x${string}`; const depositTokenContractAddress = getDepositTokenContractAddress( args.tokenTicker.toUpperCase(), @@ -99,13 +98,13 @@ export async function smartDeposit( args: [smartAccountAddress, parseUnits(args.amount, DECIMALS as number)], }); - approvalTxn = { + let approvalTxn: Transaction = { to: tokenAddress, data: approvalTxnData, value: 0n, }; - depositAndWrapTxn = { + let depositAndWrapTxn: Transaction = { to: depositTokenContractAddress, data: depositAndWrapTxnData, value: 0n, diff --git a/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts b/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts index 43e3ed7..9804665 100644 --- a/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts +++ b/agentkit-core/src/actions/getConfidentialTransferBalanceAction.ts @@ -137,8 +137,6 @@ export async function getConfidentialBalance( let tokenAddresses: `0x${string}`[] = []; const smartAccount = await wallet.getAddress(); const chainId = wallet.rpcProvider.chain?.id; - const chainEnum = getChainEnum(chainId || 43114); // Default to Avalanche C-Chain if chainId is not set - const tokenEnum = getTokenEnum(); // Currently only USDC is supported for confidential transfers // If no specific tokens requested, get all tokens from tokenMappings for the current chain if ( @@ -239,7 +237,9 @@ export async function getConfidentialBalance( /** * Get wallet balance action. */ -export class GetConfidentialBalanceAction implements AgentkitAction { +export class GetConfidentialBalanceAction + implements AgentkitAction +{ public name = "get_confidential_balance"; public description = GET_CONFIDETIAL_BALANCE_PROMPT; public argsSchema = GetConfidentialBalanceInput; diff --git a/agentkit-core/src/actions/index.ts b/agentkit-core/src/actions/index.ts index 1aea465..df80635 100644 --- a/agentkit-core/src/actions/index.ts +++ b/agentkit-core/src/actions/index.ts @@ -6,7 +6,7 @@ import { CheckTransactionAction } from "./checkTransactionAction"; import { SmartDepositAction } from "./depositTokenAction"; import { AgentkitAction, ActionSchemaAny } from "../agentkit"; import { GetAddressAction } from "./getAddressAction"; -import { SmartWithdrawTokenAction } from './withdrawTokenAction'; +import { SmartWithdrawTokenAction } from "./withdrawTokenAction"; import { GetConfidentialBalanceAction } from "./getConfidentialTransferBalanceAction"; import { SmartSwapAction, SmartBridgeAction } from "./DebridgeAction"; import { CreateAndStoreKeyAction } from "./createAndStoreKeyAction"; diff --git a/agentkit-core/src/actions/withdrawTokenAction.ts b/agentkit-core/src/actions/withdrawTokenAction.ts index 93ad1e0..16f3f9d 100644 --- a/agentkit-core/src/actions/withdrawTokenAction.ts +++ b/agentkit-core/src/actions/withdrawTokenAction.ts @@ -99,11 +99,6 @@ export async function smartWithdrawAction( `Smart Withdrawal Action: ${args.amount} ${args.tokenTicker} to ${args.destinationAddress}`, ); try { - let withdrawalApprovalTxn: Transaction, withdrawalTokenTxn: Transaction; - const depositTokenContractAddress = getDepositTokenContractAddress( - args.tokenTicker.toUpperCase(), - ); - const tokenAddress = getTokenAddress(args.tokenTicker.toUpperCase()); const tokenEnum = getTokenEnum(); const chainEnum = getChainEnum(wallet.rpcProvider.chain?.id || 43114); // Default to Avalanche C-Chain if chainId is not set const tokenConfig: TokenConfig = { @@ -116,13 +111,13 @@ export async function smartWithdrawAction( PlaintextType.uint64, args.destinationAddress, ); - withdrawalApprovalTxn = { + let withdrawalApprovalTxn: Transaction = { to: withdrawTxn[0].to as `0x${string}`, data: withdrawTxn[0].data, value: 0n, // No native currency value for token transfers }; - withdrawalTokenTxn = { + let withdrawalTokenTxn: Transaction = { to: withdrawTxn[1].to as `0x${string}`, data: withdrawTxn[1].data, value: 0n, // No native currency value for token transfers diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..9160a5f175ed2c1222944e7afd53857c3add67b9 GIT binary patch literal 226928 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≶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ⅆj0qszD<0DEdd|^qwJE{E5eInX9U4NU@*&!xG2yLR zqA)Nz4WNS7mXJdGHiZniz@k#|icSt>AQna70tvx;Td(p3qf*dd4gM<#s$Q%OQtN0i z=3pAFtzh6(Y8qIB4`95Dn7m41gE{zSyZ>4PAzrlzqQq~g2JZ1K*pXn>7FV!DBHw{I zq+0-wyc6Rm!6k+&_*E~gQJK;$*aZ^q#wdTwiNgmGWB8c#z;jnM7Sd2}(eUJ(SXkv3 zCpzJGFkDQAS4lCZ;Kc@Wp!H6lxDf3Vh65^ckc~Nt)s&WyWU`ru<1_pGNG2!5ILn9m z5WaJ+{EQN2{BVY&&^B$Bbbe=4DC2puW+;na{FY_r80ANr+*ElsO|%5R5nw=!aj~w* zg8pFI&Pa{Rb*QW94FoJt3!xa$BqXrob_=+@-64d=wc?BYof z+@1%|@5=;A+x-R~Q+7YF2?yPM} z-}rvSFeg8XAk3$22T0Z@EJyvEsy7$wdB#+$zj|bpjv&|xBBt&~A#D&^lsqLC@3PzZ zi*|VJ*o>pLiGiAfPh4my-@uY%n*epmox5cEA8p=5fbj9b-fZy5pnLU_A^a^5l86C} zJE9Zsh6LKV_Kv8PC^&^y!B+VwLwqnxsj$2ii*CWn315A%^Q**2RlVhLExDVE_x91F z1R0TfB0-4f0b=CJFg~M7hZh~*BAgv~q|=m)g~s4cM-vT_wOl#Mns-M83Elyye(LTP zUpwIYJ81#?3QsJ^60asGJi;FYTio>OBEj$VEEYC{Nf4bYIK`D^6x{7%y-Tb}f=j&> zNd>D+o}L|?o(EB)!R8z8Z?=NfeJ?tzV9wV)umGp~UR3^Irop$D`SoS+$va~dUz`>R z#^W6jtSsPtuVklDZE1K*6gAL38vDWcbvwMCBbL4SD+X%0sPB=g>}fb>FCqo-E|^Z>JS*$q~!kq8M`2?>#*?%RF)Hn(TGw?DWu5rl+@x7e7M*>E3%6p7!z zT*vltcbCs*+~6MD?JAeQ%63(`+#AQkFnG|}0bq5!Rs7w0e(=`ib*`Z9CdtFXfN&4E#Y!LJH8XIsa*-UmG(A?w%Rg+@kZbNF47w+NU zhXRu>OjC3xhczg`KFSB~QM`~FV5kZOzKYR2eNK8j9;6-7rzl5)(r`XccK(;mevo@$ zOMnbP+pP6EEg$y)%welfk7L3Vag+yG3Y5cyi~-C-jsD=RjoCAH(MVcWvrlYp(xo4k zln=OS-+He_Yvv6I%DwT6jqhHyTe?8kCK>0nMp)v~Tm$%su6Q}Tj~8F(ZgPUYNdddg zaL5AE!2L7sj8RA&?8-F{xS%zq#Gu2+87W|#U`(pV;>JaTW1IjEUjemonzq~WT*6gg z7>RvzlibR{=CDdKQmExQ6(E z^lQfAVm_$t6(l#e47!Vh56?7sKFS)!ZOHama#bksRm|$xo2`X-fJ?+mw&RM`_Kj+5 z|2|VFxL~D6lwG8Y!F#TZNuD~09qt$tB?Zpg;z>(=5)-f#+9M`aRL-*Cmc&HOF^PP zmkK4mF!CVPZ1>>Au%i+4#&J;ixJsQ3v~_e6Ul^4Mf>9g{6U?RLuwb!;C%EJ?nBnO# zs{F}*`3_O9jZg{a(0YaLqc*G6>hrs|Kzj)C`YbbJR;fcNKPjk&);DNs79TJ*DMnL|A6Kgx7^;{-_hx!($3fAgc42EOd4JM8*`nE- zUu**;6x0EB2-2P2E9ShBw>@+(UpIw<)@`$buT27Pzg=7XIC$D5!((&JH0isTWv_Io zQT0*)Hh~$BwXBKT(_?3MLCq?ix33gI<`WNs$vvBW>BPSJbdJfq*@>kx{ zw%4uC13CxIt62p=Z&up&56IK?t}gQr$lNvEZhYmqHXt+Yg?SQUT)%O6Irz=I}FrfW0H~+ZVsap1hJU0S-Ky$Tw zW>=ETm+gUidw-8Z52|K+DIIA^FaXCHDPf#2sU>89WTgV0!#0nN{jSXA)1!466fZsqC*m27fST9X3ZgF+Id+^b#e!YMCs&*jKGHmPGrwE%t; z2ZKvpWKM5Seq!#i-+r3;+c-4Fa)o!T@`xuX{+_5DB3mOd+z875RBo=2g^hDUQv*A# zUc0?!`ZlQ7gU;mvh_7UB7&OT^ zBlyM%le$XApeT6&_K+&Vgo;<{#;z1-^FSbnA$QiT@9rOxXVY{=GI>|#uq-b&sIaj) zJ#C)s@k3dt9&zCEDEm^j_jaW+d3L>TIC-0or!UT7&d2obHorNF&#rMA|;rxWnH3 z(d^EVAZ2963X)OW_8PriUM|H*kOv$}R7a&z=Z+w^k+L%9F%;%FlI1R+>eS2J8bI0i z7)_rc3rL3Gq&;9Bu>j^U(-&JSo4?+j8bOj;;jwyYiuRCKa;p)~d-L2gD>xYF{aqC=O-cW)kFg;eOPd3x1m`XK1*P-AW-v1@@`CLm z4L;Qu6jm()jw)7K6k{V-2o5^F&|L3Yc9C}l3!|sMez$!Ht~QBD#USjS=te`Mpy9%= zAB}Sc?JqnsZH>Ro4E_ofu_ATt9XUtk8-XIk_>JvUf)UY7Ie^RjLkZb`Gp?Gx09Ua@ zdWYMouxlRi{IW_w_)t<^Xm*a_4U(_73_41a99&Ngin>MQVCRTU?(w>j`Sqe8`T7qq z0iSu5zFA7=yGM@noFEXOb9Q~$4HtiA^29tmJhR>0a~mVt4MboN75xlT@OLhc`{hSe zm2jQ=lZBDROJB7a+=K)zc{M*JUro0nZK?8~?^lQ~*=<;X;!hnb8iJYj?cfI<1+YKl@3K{(cz8MCfXi}i!i*!QM1~K`4kLX#w=Kv;3EWm_! zF9rcjIJZD`b7=Qf%W}E5&^avy?0x98W40Hl%p;#3`qsL#i|*c-ADEO2Y*mc*>8~8Q zFko|-{_zJ55a)9)NAtkrD{R0|bzIK}h)gEsA+~SeT)bZC@>dGLthE)12VsTT8_CO| z<9s(2bQ~+G5CG{R+e4VxlmxV>`Zb34ObLZYtVw&6w`~LlT2HNI8{2fAuG{rqzNJDx zT9>&KQeNv5sF7t0XY$9-&WH>ALG@}9)vb<=5UBbNGU`$Qt)o^&+pDF+sJ-QPnjfD6 zYMPv2Y*GwqPvxo6`;981FA!Yl@AcGSbv`CxiH8K1CSgFX8r%oh5G?H5{2po%4G`o! zP@BVLlN&%{d$!|dEu-23OohHij`R345c=3A#te=Y05h!&(izb(du-aRYKVHAFM@tUEVARAZt>}20duhwi0SAw_F(N zRq(()_FL{>OW+>hlvOhJPN4FTS&{VWQzHkoj!qhxF#j~1QvjI0rnKo%ifvM?;9&ImFGL7s)5%icxv5*mw?9B@~ywH__pHG zlZJUq>(Mtr5AJ%XUv}MNYq>Sc3;%om{o!}Vujjx0?(`!|`QE=TzdZlu?N_h9c%}Q- zyN6#8va2JzhnGM8_kX|r&%gfm_0P`<R z1}g0P(^2ep