@agentek/tools
Version:
Blockchain tools for AI agents
297 lines • 11.5 kB
JavaScript
import { z } from "zod";
import { createTool } from "../client.js";
import { erc20Abi, formatUnits } from "viem";
import { erc20Chains } from "./constants.js";
const getAllowanceParameters = z.object({
token: z.string().describe("The token address"),
owner: z.string().describe("The token owner's address"),
spender: z.string().describe("The spender's address"),
chainId: z
.number()
.optional()
.describe("If not specified, returns approval for all supported chains."),
});
const getBalanceOfParameters = z.object({
token: z.string().describe("The token address"),
owner: z.string().describe("The token owner's address"),
chainId: z
.number()
.optional()
.describe("If not specified, returns balance for all supported chains."),
});
const getTotalSupplyParameters = z.object({
token: z.string().describe("The token address"),
chainId: z
.number()
.optional()
.describe("If not specified, returns total supply for all supported chains."),
});
const getDecimalsParameters = z.object({
token: z.string().describe("The token address"),
chainId: z
.number()
.optional()
.describe("If not specified, returns decimals for all supported chains."),
});
const getNameParameters = z.object({
token: z.string().describe("The token address"),
chainId: z
.number()
.optional()
.describe("If not specified, returns name for all supported chains."),
});
const getSymbolParameters = z.object({
token: z.string().describe("The token address"),
chainId: z
.number()
.optional()
.describe("If not specified, returns symbol for all supported chains."),
});
const tokenMetadataParameters = z.object({
token: z.string().describe("The token address"),
chainId: z.number().describe("The token chain"),
});
export const getAllowanceTool = createTool({
name: "getAllowance",
description: "Gets the ERC20 token allowance between an owner and spender",
supportedChains: erc20Chains,
parameters: getAllowanceParameters,
execute: async (client, args) => {
const { token, owner, spender, chainId } = args;
const chains = client.filterSupportedChains(erc20Chains, chainId);
const allowances = await Promise.all(chains.map(async (chain) => {
const publicClient = client.getPublicClient(chain.id);
try {
const decimals = await publicClient.readContract({
address: token,
abi: erc20Abi,
functionName: "decimals",
});
const allowance = await publicClient.readContract({
address: token,
abi: erc20Abi,
functionName: "allowance",
args: [owner, spender],
});
return {
chain: chain.id,
allowance: formatUnits(allowance, decimals),
};
}
catch (error) {
// @TODO type specific viem short errors
return {
chain: chain.id,
error: `Failed to fetch allowance: ${typeof error === "object" && error ? ("shortMessage" in error ? error.shortMessage : "message" in error ? error.message : "Unknown error") : String(error)}`,
};
}
}));
return allowances;
},
});
export const getBalanceOfTool = createTool({
name: "getBalanceOf",
description: "Gets the ERC20 token balance of an address",
supportedChains: erc20Chains,
parameters: getBalanceOfParameters,
execute: async (client, args) => {
const { token, owner, chainId } = args;
const chains = client.filterSupportedChains(erc20Chains, chainId);
const balances = await Promise.all(chains.map(async (chain) => {
const publicClient = client.getPublicClient(chain.id);
try {
const decimals = await publicClient.readContract({
address: token,
abi: erc20Abi,
functionName: "decimals",
});
const balance = await publicClient.readContract({
address: token,
abi: erc20Abi,
functionName: "balanceOf",
args: [owner],
});
return {
chain: chain.id,
balance: formatUnits(balance, decimals),
};
}
catch (error) {
return {
chain: chain.id,
error: `Failed to fetch balance: ${typeof error === "object" && error ? ("shortMessage" in error ? error.shortMessage : "message" in error ? error.message : "Unknown error") : String(error)}`,
};
}
}));
return balances;
},
});
export const getTotalSupplyTool = createTool({
name: "getTotalSupply",
description: "Gets the total supply of an ERC20 token",
supportedChains: erc20Chains,
parameters: getTotalSupplyParameters,
execute: async (client, args) => {
const { token, chainId } = args;
const chains = client.filterSupportedChains(erc20Chains, chainId);
const supplies = await Promise.all(chains.map(async (chain) => {
const publicClient = client.getPublicClient(chain.id);
try {
const decimals = await publicClient.readContract({
address: token,
abi: erc20Abi,
functionName: "decimals",
});
const totalSupply = await publicClient.readContract({
address: token,
abi: erc20Abi,
functionName: "totalSupply",
});
return {
chain: chain.id,
totalSupply: formatUnits(totalSupply, decimals),
};
}
catch (error) {
return {
chain: chain.id,
error: `Failed to fetch total supply: ${typeof error === "object" && error ? ("shortMessage" in error ? error.shortMessage : "message" in error ? error.message : "Unknown error") : String(error)}`,
};
}
}));
return supplies;
},
});
export const getDecimalsTool = createTool({
name: "getDecimals",
description: "Gets the number of decimals of an ERC20 token",
supportedChains: erc20Chains,
parameters: getDecimalsParameters,
execute: async (client, args) => {
const { token, chainId } = args;
const chains = client.filterSupportedChains(erc20Chains, chainId);
const tokenDecimals = await Promise.all(chains.map(async (chain) => {
const publicClient = client.getPublicClient(chain.id);
try {
const decimals = await publicClient.readContract({
address: token,
abi: erc20Abi,
functionName: "decimals",
});
return {
chain: chain.id,
decimals,
};
}
catch (error) {
return {
chain: chain.id,
error: `Failed to fetch decimals: ${typeof error === "object" && error ? ("shortMessage" in error ? error.shortMessage : "message" in error ? error.message : "Unknown error") : String(error)}`,
};
}
}));
return tokenDecimals;
},
});
export const getNameTool = createTool({
name: "getName",
description: "Gets the name of an ERC20 token",
supportedChains: erc20Chains,
parameters: getNameParameters,
execute: async (client, args) => {
const { token, chainId } = args;
const chains = client.filterSupportedChains(erc20Chains, chainId);
const names = await Promise.all(chains.map(async (chain) => {
const publicClient = client.getPublicClient(chain.id);
try {
const name = await publicClient.readContract({
address: token,
abi: erc20Abi,
functionName: "name",
});
return {
chain: chain.id,
name,
};
}
catch (error) {
return {
chain: chain.id,
error: `Failed to fetch name: ${typeof error === "object" && error ? ("shortMessage" in error ? error.shortMessage : "message" in error ? error.message : "Unknown error") : String(error)}`,
};
}
}));
return names;
},
});
export const getSymbolTool = createTool({
name: "getSymbol",
description: "Gets the symbol of an ERC20 token",
supportedChains: erc20Chains,
parameters: getSymbolParameters,
execute: async (client, args) => {
const { token, chainId } = args;
const chains = client.filterSupportedChains(erc20Chains, chainId);
const symbols = await Promise.all(chains.map(async (chain) => {
const publicClient = client.getPublicClient(chain.id);
try {
const symbol = await publicClient.readContract({
address: token,
abi: erc20Abi,
functionName: "symbol",
});
return {
chain: chain.id,
symbol,
};
}
catch (error) {
return {
chain: chain.id,
error: `Failed to fetch symbol: ${typeof error === "object" && error ? ("shortMessage" in error ? error.shortMessage : "message" in error ? error.message : "Unknown error") : String(error)}`,
};
}
}));
return symbols;
},
});
export const getTokenMetadataTool = createTool({
name: "getTokenMetadata",
description: "Gets all metadata (name, symbol, decimals, totalSupply) of an ERC20 token",
supportedChains: erc20Chains,
parameters: tokenMetadataParameters,
execute: async (client, args) => {
const { token, chainId } = args;
const publicClient = client.getPublicClient(chainId);
const [name, symbol, decimals, totalSupply] = await Promise.all([
publicClient.readContract({
address: token,
abi: erc20Abi,
functionName: "name",
}),
publicClient.readContract({
address: token,
abi: erc20Abi,
functionName: "symbol",
}),
publicClient.readContract({
address: token,
abi: erc20Abi,
functionName: "decimals",
}),
publicClient.readContract({
address: token,
abi: erc20Abi,
functionName: "totalSupply",
}),
]);
return {
chain: chainId,
name,
symbol,
decimals,
totalSupply: formatUnits(totalSupply, decimals),
};
},
});
//# sourceMappingURL=tools.js.map