diff --git a/.env.example b/.env.example index b3e1b01ae66..92011c3fd26 100644 --- a/.env.example +++ b/.env.example @@ -659,6 +659,10 @@ AKASH_MANIFEST_VALIDATION_LEVEL=strict QUAI_PRIVATE_KEY= QUAI_RPC_URL=https://rpc.quai.network +# 0x +ZERO_EX_API_KEY= +ALCHEMY_HTTP_TRANSPORT_URL= + # Instagram Configuration INSTAGRAM_DRY_RUN=false INSTAGRAM_USERNAME= # Account username diff --git a/agent/src/index.ts b/agent/src/index.ts index e098057279f..eae84ead325 100644 --- a/agent/src/index.ts +++ b/agent/src/index.ts @@ -119,6 +119,7 @@ import { zksyncEraPlugin } from "@elizaos/plugin-zksync-era"; import { nvidiaNimPlugin } from "@elizaos/plugin-nvidia-nim"; +import { zxPlugin } from "@elizaos/plugin-0x"; import Database from "better-sqlite3"; import fs from "fs"; import net from "net"; @@ -1081,6 +1082,7 @@ export async function createAgent( getSecret(character, "RESERVOIR_API_KEY") ? createNFTCollectionsPlugin() : null, + getSecret(character, "ZERO_EX_API_KEY") ? zxPlugin : null, getSecret(character, "PYTH_TESTNET_PROGRAM_KEY") || getSecret(character, "PYTH_MAINNET_PROGRAM_KEY") ? pythDataPlugin diff --git a/packages/core/src/generation.ts b/packages/core/src/generation.ts index 618746645b5..a4fb01f376c 100644 --- a/packages/core/src/generation.ts +++ b/packages/core/src/generation.ts @@ -574,8 +574,14 @@ export async function generateText({ const openai = createOpenAI({ apiKey, baseURL: endpoint, - fetch: async (input: RequestInfo | URL, init?: RequestInit): Promise => { - const url = typeof input === 'string' ? input : input.toString(); + fetch: async ( + input: RequestInfo | URL, + init?: RequestInit + ): Promise => { + const url = + typeof input === "string" + ? input + : input.toString(); const chain_id = runtime.getSetting("ETERNALAI_CHAIN_ID") || "45762"; @@ -588,9 +594,11 @@ export async function generateText({ const fetching = await runtime.fetch(url, options); - if (parseBooleanFromText( - runtime.getSetting("ETERNALAI_LOG") - )) { + if ( + parseBooleanFromText( + runtime.getSetting("ETERNALAI_LOG") + ) + ) { elizaLogger.info( "Request data: ", JSON.stringify(options, null, 2) @@ -1226,30 +1234,35 @@ export async function generateText({ messages: [ { role: "system", - content: runtime.character.system ?? settings.SYSTEM_PROMPT ?? "You are a helpful assistant" + content: + runtime.character.system ?? + settings.SYSTEM_PROMPT ?? + "You are a helpful assistant", }, { role: "user", - content: context - } + content: context, + }, ], max_tokens: max_response_length, - stream: false + stream: false, }; - const fetchResponse = await runtime.fetch(endpoint+'/llm', { + const fetchResponse = await runtime.fetch(endpoint + "/llm", { method: "POST", headers: { - "accept": "text/event-stream", + accept: "text/event-stream", "Content-Type": "application/json", - "Authorization": "Bearer eliza-app-llm" + Authorization: "Bearer eliza-app-llm", }, - body: JSON.stringify(requestBody) + body: JSON.stringify(requestBody), }); if (!fetchResponse.ok) { const errorText = await fetchResponse.text(); - throw new Error(`Livepeer request failed (${fetchResponse.status}): ${errorText}`); + throw new Error( + `Livepeer request failed (${fetchResponse.status}): ${errorText}` + ); } const json = await fetchResponse.json(); @@ -1258,8 +1271,13 @@ export async function generateText({ throw new Error("Invalid response format from Livepeer"); } - response = json.choices[0].message.content.replace(/<\|start_header_id\|>assistant<\|end_header_id\|>\n\n/, ''); - elizaLogger.debug("Successfully received response from Livepeer model"); + response = json.choices[0].message.content.replace( + /<\|start_header_id\|>assistant<\|end_header_id\|>\n\n/, + "" + ); + elizaLogger.debug( + "Successfully received response from Livepeer model" + ); break; } @@ -1641,8 +1659,8 @@ export const generateImage = async ( return runtime.getSetting("FAL_API_KEY"); case ModelProviderName.OPENAI: return runtime.getSetting("OPENAI_API_KEY"); - case ModelProviderName.VENICE: - return runtime.getSetting("VENICE_API_KEY"); + case ModelProviderName.VENICE: + return runtime.getSetting("VENICE_API_KEY"); case ModelProviderName.LIVEPEER: return runtime.getSetting("LIVEPEER_GATEWAY_URL"); default: @@ -2485,12 +2503,14 @@ async function handleLivepeer({ }: ProviderOptions): Promise> { console.log("Livepeer provider api key:", apiKey); if (!apiKey) { - throw new Error("Livepeer provider requires LIVEPEER_GATEWAY_URL to be configured"); + throw new Error( + "Livepeer provider requires LIVEPEER_GATEWAY_URL to be configured" + ); } const livepeerClient = createOpenAI({ apiKey, - baseURL: apiKey // Use the apiKey as the baseURL since it contains the gateway URL + baseURL: apiKey, // Use the apiKey as the baseURL since it contains the gateway URL }); return await aiGenerateObject({ @@ -2503,7 +2523,6 @@ async function handleLivepeer({ }); } - // Add type definition for Together AI response interface TogetherAIImageResponse { data: Array<{ @@ -2556,4 +2575,4 @@ export async function generateTweetActions({ await new Promise((resolve) => setTimeout(resolve, retryDelay)); retryDelay *= 2; } -} \ No newline at end of file +} diff --git a/packages/plugin-0x/README.md b/packages/plugin-0x/README.md new file mode 100644 index 00000000000..42cd84804c2 --- /dev/null +++ b/packages/plugin-0x/README.md @@ -0,0 +1,86 @@ +# @elizaos/plugin-0x + +This plugin enables Eliza to interact with the 0x Protocol, providing decentralized exchange capabilities across multiple evm blockchain networks with optimized token swaps and liquidity aggregation. + +Supported networks include: + - Ethereum Mainnet + - Polygon + - Binance Smart Chain + - Arbitrum + - Optimism + - Base + - Linea + - Scroll + - Avalanche + - Blast + +## Configuration + +Set the following environment variables: + +```env +WALLET_PRIVATE_KEY=your_private_key +ZERO_EX_API_KEY=your_0x_api_key +{chain}_RPC_URL=your_rpc_endpoint +``` + +## Installation + +```bash +pnpm install @elizaos/plugin-0x +``` + +## Usage + +### Basic Integration + +```typescript +import { zeroExPlugin } from "@elizaos/plugin-0x"; +``` + +### Example Usage + +The plugin supports natural language commands for ETH transfers: + +```typescript +"I want to convert 1 ETH to USDC on ethereum chain"; +"Give me the quote"; +"Execute it"; +``` + +## Available Actions + +The plugin provides the following actions: + +1. **GET_INDICATIVE_PRICE_0X**: Get indicative prices for token swaps + - Example: "Get quote for swapping 1 ETH to USDC on Ethereum chain" + - Example: "Price check for trading 100 USDT to MATIC on Polygon chain" + +2. **GET_QUOTE_0X**: Get the quote for the swap. Quote expires in 5mins. (This action is triggered only after user has requested for an indicative price. No need to repeat the buy/sell tokens because the last indicative price will be stored in the memory) + - Example: "Get quote" + +3. **EXECUTE_SWAP_0X**: Execute token swaps. (Action is triggered only after user has gotten a quote) + - Example: "Execute the swap" + +## Security Best Practices + +1. **Environment Variables** + - Never commit private keys to version control + - Use secure environment variable management + - Rotate private keys periodically + +## Contributing + +Contributions are welcome! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file for more information. + +## Credits + +This plugin integrates with: +- [0x Protocol](https://0x.org/) + +For more information about 0x capabilities: +- [0x API Documentation](https://0x.org/docs/api) + +## License + +This plugin is part of the Eliza project. See the main project repository for license information. \ No newline at end of file diff --git a/packages/plugin-0x/package.json b/packages/plugin-0x/package.json new file mode 100644 index 00000000000..a11a65851c4 --- /dev/null +++ b/packages/plugin-0x/package.json @@ -0,0 +1,36 @@ +{ + "name": "@elizaos/plugin-0x", + "version": "0.1.8", + "type": "module", + "main": "dist/index.js", + "module": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + "./package.json": "./package.json", + ".": { + "import": { + "@elizaos/source": "./src/index.ts", + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "tsup --format esm --dts", + "dev": "tsup --format esm --dts --watch", + "test": "vitest" + }, + "dependencies": { + "@0x/swap-ts-sdk": "2.1.1" + }, + "devDependencies": { + "tsup": "^8.0.1" + }, + "peerDependencies": { + "@elizaos/core": "workspace:*", + "zod": "^3.22.4" + } +} diff --git a/packages/plugin-0x/src/EVMtokenRegistry.ts b/packages/plugin-0x/src/EVMtokenRegistry.ts new file mode 100644 index 00000000000..51a674b941d --- /dev/null +++ b/packages/plugin-0x/src/EVMtokenRegistry.ts @@ -0,0 +1,133 @@ +import { elizaLogger } from "@elizaos/core"; +import { + Chains, + TokenMetadata, + TrustWalletGithubJson, + TrustWalletTokenMetadata, +} from "./types"; +import { NATIVE_TOKENS } from "./constants"; + +export class EVMTokenRegistry { + private static instance: EVMTokenRegistry; + private chainTokenMaps: Map>; + private initializedChains: Set; + + private static CHAIN_NAMES: Record = Object.fromEntries( + Object.keys(Chains) + .map(name => [Chains[name as keyof typeof Chains], name.toLowerCase()]) + ); + + private constructor() { + this.chainTokenMaps = new Map(); + this.initializedChains = new Set(); + } + + public static getInstance(): EVMTokenRegistry { + if (!EVMTokenRegistry.instance) { + EVMTokenRegistry.instance = new EVMTokenRegistry(); + } + return EVMTokenRegistry.instance; + } + + private async fetchTokenList( + chainId: number + ): Promise { + const chainName = EVMTokenRegistry.CHAIN_NAMES[chainId]; + if (!chainName) { + throw new Error(`Unsupported chain ID: ${chainId}`); + } + + const url = `https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/${chainName}/tokenlist.json`; + + try { + const response = await fetch(url); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const data: TrustWalletGithubJson = await response.json(); + return data.tokens; + } catch (error) { + elizaLogger.error( + `Failed to fetch token list for chain ${chainName}:`, + error + ); + throw error; + } + } + + public async initializeChain(chainId: number): Promise { + if (this.initializedChains.has(chainId)) return; + + const tokens = await this.fetchTokenList(chainId); + const tokenMap = new Map(); + + // Add native token first + const nativeToken = NATIVE_TOKENS[chainId]; + if (nativeToken) { + tokenMap.set(nativeToken.symbol.toUpperCase(), nativeToken); + } + + for (const token of tokens) { + const { pairs, ...restToken } = token; + tokenMap.set(token.symbol.toUpperCase(), { + chainId, + ...restToken, + }); + } + + this.chainTokenMaps.set(chainId, tokenMap); + // Only add to initializedChains if tokens were fetched successfully + if (tokenMap.size > 0) { + this.initializedChains.add(chainId); + } + } + + public getTokenBySymbol( + symbol: string, + chainId: number + ): TokenMetadata | undefined { + if (!EVMTokenRegistry.CHAIN_NAMES[chainId]) { + throw new Error(`Unsupported chain ID: ${chainId}`); + } + + const chainTokens = this.chainTokenMaps.get(chainId); + if (!chainTokens) return undefined; + + return chainTokens.get(symbol.toUpperCase()); + } + + public getTokenByAddress( + address: string, + chainId: number + ): TokenMetadata | undefined { + if (!EVMTokenRegistry.CHAIN_NAMES[chainId]) { + throw new Error(`Unsupported chain ID: ${chainId}`); + } + + const tokens = this.chainTokenMaps.get(chainId)?.values(); + if (!tokens) return undefined; + + const normalizedAddress = address.toLowerCase(); + for (const token of tokens) { + if (token.address.toLowerCase() === normalizedAddress) { + return token; + } + } + return undefined; + } + + public async getAllTokensForChain( + chainId: number + ): Promise { + if (!EVMTokenRegistry.CHAIN_NAMES[chainId]) { + throw new Error(`Unsupported chain ID: ${chainId}`); + } + + await this.initializeChain(chainId); + return Array.from(this.chainTokenMaps.get(chainId)?.values() ?? []); + } + + public isChainSupported(chainId: number): boolean { + return chainId in EVMTokenRegistry.CHAIN_NAMES; + } +} diff --git a/packages/plugin-0x/src/actions/getIndicativePrice.ts b/packages/plugin-0x/src/actions/getIndicativePrice.ts new file mode 100644 index 00000000000..b73ceee4ca8 --- /dev/null +++ b/packages/plugin-0x/src/actions/getIndicativePrice.ts @@ -0,0 +1,294 @@ +import { + Action, + IAgentRuntime, + Memory, + State, + HandlerCallback, + elizaLogger, + composeContext, + ModelClass, + generateObject, + MemoryManager, +} from "@elizaos/core"; +import { createClientV2 } from "@0x/swap-ts-sdk"; +import { getIndicativePriceTemplate } from "../templates"; +import { z } from "zod"; +import { Chains, GetIndicativePriceResponse, PriceInquiry } from "../types"; +import { parseUnits } from "viem"; +import { CHAIN_NAMES, ZX_MEMORY } from "../constants"; +import { EVMTokenRegistry } from "../EVMtokenRegistry"; + +export const IndicativePriceSchema = z.object({ + sellTokenSymbol: z.string().nullable(), + sellAmount: z.number().nullable(), + buyTokenSymbol: z.string().nullable(), + chain: z.string().nullable(), +}); + +export interface IndicativePriceContent { + sellTokenSymbol: string; + sellAmount: number; + buyTokenSymbol: string; + chain: string; +} + +export const getIndicativePrice: Action = { + name: "GET_INDICATIVE_PRICE_0X", + similes: [], + suppressInitialMessage: true, + description: + "Get indicative price for a swap from 0x when user wants to convert their tokens", + validate: async (runtime: IAgentRuntime) => { + return !!runtime.getSetting("ZERO_EX_API_KEY"); + }, + handler: async ( + runtime: IAgentRuntime, + message: Memory, + state: State, + options: Record, + callback: HandlerCallback + ) => { + const supportedChains = Object.keys(Chains).join(" | "); + + state = !state + ? await runtime.composeState(message, { supportedChains }) + : await runtime.updateRecentMessageState(state); + + const context = composeContext({ + state, + template: getIndicativePriceTemplate, + }); + + const content = await generateObject({ + runtime, + context, + modelClass: ModelClass.SMALL, + schema: IndicativePriceSchema, + }); + + if (!isIndicativePriceContent(content.object)) { + const missingFields = getMissingIndicativePriceContent( + content.object + ); + callback({ + text: `Need more information about the swap. Please provide me ${missingFields}`, + }); + return; + } + + const { sellTokenSymbol, sellAmount, buyTokenSymbol, chain } = + content.object; + + // Convert chain string to chainId + const chainId = Chains[chain.toLowerCase() as keyof typeof Chains]; + if (!chainId) { + callback({ + text: `Unsupported chain: ${chain}. Supported chains are: ${Object.keys( + Chains + ) + .filter((k) => isNaN(Number(k))) + .join(", ")}`, + }); + return; + } + + const evmTokenRegistry = EVMTokenRegistry.getInstance(); + if (evmTokenRegistry.isChainSupported(chainId)) { + await evmTokenRegistry.initializeChain(chainId); + } else { + callback({ + text: `Chain ${chain} is not supported for token swaps.`, + }); + return; + } + + const sellTokenMetadata = evmTokenRegistry.getTokenBySymbol( + sellTokenSymbol, + chainId + ); + const buyTokenMetadata = evmTokenRegistry.getTokenBySymbol( + buyTokenSymbol, + chainId + ); + + if (!sellTokenMetadata || !buyTokenMetadata) { + const missingTokens = []; + if (!sellTokenMetadata) missingTokens.push(`'${sellTokenSymbol}'`); + if (!buyTokenMetadata) missingTokens.push(`'${buyTokenSymbol}'`); + + callback({ + text: `Token${missingTokens.length > 1 ? 's' : ''} ${missingTokens.join(' and ')} not found on ${chain}. Please check the token symbols and chain.`, + }); + return; + } + + elizaLogger.info("Getting indicative price for:", { + sellToken: sellTokenMetadata, + buyToken: buyTokenMetadata, + amount: sellAmount, + }); + + const zxClient = createClientV2({ + apiKey: runtime.getSetting("ZERO_EX_API_KEY"), + }); + + const sellAmountBaseUnits = parseUnits( + sellAmount.toString(), + sellTokenMetadata.decimals + ).toString(); + + try { + const price = (await zxClient.swap.permit2.getPrice.query({ + sellAmount: sellAmountBaseUnits, + sellToken: sellTokenMetadata.address, + buyToken: buyTokenMetadata.address, + chainId, + })) as GetIndicativePriceResponse; + + // Format amounts to human-readable numbers + const buyAmount = + Number(price.buyAmount) / + Math.pow(10, buyTokenMetadata.decimals); + const sellAmount = + Number(price.sellAmount) / + Math.pow(10, sellTokenMetadata.decimals); + + await storePriceInquiryToMemory(runtime, message, { + sellTokenObject: sellTokenMetadata, + buyTokenObject: buyTokenMetadata, + sellAmountBaseUnits, + chainId, + timestamp: new Date().toISOString(), + }); + + // Updated formatted response to include chain + const formattedResponse = [ + `💱 Swap Details:`, + `────────────────`, + `📤 Sell: ${sellAmount.toFixed(4)} ${sellTokenMetadata.symbol}`, + `📥 Buy: ${buyAmount.toFixed(4)} ${buyTokenMetadata.symbol}`, + `📊 Rate: 1 ${sellTokenMetadata.symbol} = ${(buyAmount / sellAmount).toFixed(4)} ${buyTokenMetadata.symbol}`, + `🔗 Chain: ${CHAIN_NAMES[chainId]}`, + `────────────────`, + `💫 Happy with the price? Type 'quote' to continue`, + ].join("\n"); + + callback({ text: formattedResponse }); + return true; + } catch (error) { + elizaLogger.error("Error getting price:", error); + callback({ + text: `Error getting price: ${error.message || error}`, + content: { error: error.message || String(error) }, + }); + return false; + } + }, + examples: [ + [ + { + user: "{{user1}}", + content: { + text: "What's the price of 2 ETH in USDC on Optimism?", + }, + }, + { + user: "{{agent}}", + content: { + text: "Let me check the current exchange rate for ETH/USDC on Optimism.", + action: "GET_INDICATIVE_PRICE_0X", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "I want to swap WETH for USDT on Arbitrum", + }, + }, + { + user: "{{agent}}", + content: { + text: "I'll help you check the price. How much WETH would you like to swap?", + action: "GET_INDICATIVE_PRICE_0X", + }, + }, + { + user: "{{user1}}", + content: { + text: "5 WETH", + }, + }, + { + user: "{{agent}}", + content: { + text: "Let me get the indicative price for 5 WETH to USDT on Arbitrum.", + action: "GET_INDICATIVE_PRICE_0X", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Price check for 1000 USDC to WETH on Base", + }, + }, + { + user: "{{agent}}", + content: { + text: "I'll check the current exchange rate for 1000 USDC to WETH on Base network.", + action: "GET_INDICATIVE_PRICE_0X", + }, + }, + ], + ], +}; + +export const isIndicativePriceContent = ( + object: any +): object is IndicativePriceContent => { + if (IndicativePriceSchema.safeParse(object).success) { + return true; + } + return false; +}; + +export const getMissingIndicativePriceContent = ( + content: Partial +): string => { + const missingFields = []; + + if (typeof content.sellTokenSymbol !== "string") + missingFields.push("sell token"); + if (typeof content.buyTokenSymbol !== "string") + missingFields.push("buy token"); + if (typeof content.sellAmount !== "number") + missingFields.push("sell amount"); + + return missingFields.join(" and "); +}; + +export const storePriceInquiryToMemory = async ( + runtime: IAgentRuntime, + message: Memory, + priceInquiry: PriceInquiry +) => { + const memory: Memory = { + roomId: message.roomId, + userId: message.userId, + agentId: runtime.agentId, + content: { + text: JSON.stringify(priceInquiry), + type: ZX_MEMORY.price.type, + }, + }; + + const memoryManager = new MemoryManager({ + runtime, + tableName: ZX_MEMORY.price.tableName, + }); + + await memoryManager.createMemory(memory); +}; diff --git a/packages/plugin-0x/src/actions/getQuote.ts b/packages/plugin-0x/src/actions/getQuote.ts new file mode 100644 index 00000000000..9d50beb94d1 --- /dev/null +++ b/packages/plugin-0x/src/actions/getQuote.ts @@ -0,0 +1,339 @@ +import { + Action, + IAgentRuntime, + Memory, + State, + HandlerCallback, + elizaLogger, + MemoryManager, +} from "@elizaos/core"; +import { GetQuoteResponse, PriceInquiry, Quote } from "../types"; +import { formatTokenAmount } from "../utils"; +import { CHAIN_NAMES, NATIVE_TOKENS, ZX_MEMORY } from "../constants"; +import { createClientV2 } from "@0x/swap-ts-sdk"; +import { formatUnits } from "viem"; + +export const getQuote: Action = { + name: "GET_QUOTE_0X", + similes: [], + suppressInitialMessage: true, + description: + "Get a firm quote for a swap from 0x when user wants to execute a trade. This action is triggered only after user has requested for an indicative price.", + validate: async (runtime: IAgentRuntime) => { + return !!runtime.getSetting("ZERO_EX_API_KEY"); + }, + handler: async ( + runtime: IAgentRuntime, + message: Memory, + state: State, + options: Record, + callback: HandlerCallback + ) => { + const latestPriceInquiry = await retrieveLatestPriceInquiry( + runtime, + message + ); + if (!latestPriceInquiry) { + callback({ + text: "Please provide me the details of the swap.", + }); + return; + } + + const { + sellTokenObject, + sellAmountBaseUnits, + buyTokenObject, + chainId, + } = latestPriceInquiry; + + const zxClient = createClientV2({ + apiKey: runtime.getSetting("ZERO_EX_API_KEY"), + }); + + try { + const quote = (await zxClient.swap.permit2.getQuote.query({ + sellAmount: sellAmountBaseUnits, + sellToken: sellTokenObject.address, + buyToken: buyTokenObject.address, + chainId: chainId, + taker: runtime.getSetting("WALLET_PUBLIC_ADDRESS"), + })) as GetQuoteResponse; + + await storeQuoteToMemory(runtime, message, { + sellTokenObject, + buyTokenObject, + sellAmountBaseUnits, + chainId, + quote, + timestamp: new Date().toISOString(), + }); + + if (!quote.liquidityAvailable) { + callback({ + text: "No liquidity available for this swap. Please try again with a different token or amount.", + }); + return; + } + + const buyAmountBaseUnitsQuoted = formatUnits( + BigInt(quote.buyAmount), + buyTokenObject.decimals + ); + + const sellAmountBaseUnitsQuoted = formatUnits( + BigInt(quote.sellAmount), + sellTokenObject.decimals + ); + + const warnings = []; + if (quote.issues?.balance) { + warnings.push( + `⚠️ Warnings:`, + ` • Insufficient balance (Have ${formatTokenAmount( + quote.issues.balance.actual, + quote.issues.balance.token, + chainId + )})` + ); + } + + const formattedResponse = [ + `🎯 Firm Quote Details:`, + `────────────────`, + // Basic swap details (same as price) + `📤 Sell: ${formatTokenAmount( + quote.sellAmount, + sellTokenObject.address, + chainId + )}`, + `📥 Buy: ${formatTokenAmount( + quote.buyAmount, + buyTokenObject.address, + chainId + )}`, + `📊 Rate: 1 ${sellTokenObject.symbol} = ${( + Number(buyAmountBaseUnitsQuoted) / + Number(sellAmountBaseUnitsQuoted) + ).toFixed(4)} ${buyTokenObject.symbol}`, + + // New information specific to quote + `💱 Minimum Buy Amount: ${formatTokenAmount( + quote.minBuyAmount, + quote.buyToken, + chainId + )}`, + + // Fee breakdown + `💰 Fees Breakdown:`, + ` • 0x Protocol Fee: ${formatTokenAmount( + quote.fees.zeroExFee?.amount, + quote.fees.zeroExFee?.token, + chainId + )}`, + ` • Integrator Fee: ${formatTokenAmount( + quote.fees.integratorFee?.amount, + quote.fees.integratorFee?.token, + chainId + )}`, + ` • Network Gas Fee: ${ + quote.totalNetworkFee + ? formatTokenAmount( + quote.totalNetworkFee, + NATIVE_TOKENS[chainId].address, + chainId + ) + : "Will be estimated at execution" + }`, + + ...formatRouteInfo(quote), + + // Chain + `🔗 Chain: ${CHAIN_NAMES[chainId]}`, + + ...(warnings.length > 0 ? warnings : []), + + `────────────────`, + `💫 Ready to execute? Type 'execute' to continue`, + ] + .filter(Boolean) + .join("\n"); + + callback({ + text: formattedResponse, + }); + return true; + } catch (error) { + elizaLogger.error("Error getting quote:", error); + if (callback) { + callback({ + text: `Error getting quote: ${error.message}`, + content: { error: error.message || String(error) }, + }); + } + return false; + } + }, + examples: [ + [ + { + user: "{{user1}}", + content: { + text: "Get me a quote for 500 USDC to WETH on Optimism", + }, + }, + { + user: "{{agent}}", + content: { + text: "I'll fetch a firm quote for swapping 500 USDC to WETH on Optimism.", + action: "GET_QUOTE_0X", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "Quote for 2.5 WETH to USDT on Arbitrum please", + }, + }, + { + user: "{{agent}}", + content: { + text: "I'll get you a firm quote for swapping 2.5 WETH to USDT on Arbitrum.", + action: "GET_QUOTE_0X", + }, + }, + ], + [ + { + user: "{{user1}}", + content: { + text: "quote 100 MATIC to USDC on Polygon", + }, + }, + { + user: "{{agent}}", + content: { + text: "I'll fetch a firm quote for swapping 100 MATIC to USDC on Polygon.", + action: "GET_QUOTE_0X", + }, + }, + ], + ], +}; + +const formatTime = (time: string) => { + const expirationDate = new Date(parseInt(time) * 1000); + + // Format: "Mar 15, 2:30 PM" + const formattedTime = expirationDate.toLocaleString(undefined, { + month: "short", + day: "numeric", + hour: "numeric", + minute: "2-digit", + hour12: true, + }); + + return `${formattedTime}`; +}; + +export const retrieveLatestPriceInquiry = async ( + runtime: IAgentRuntime, + message: Memory +): Promise => { + const memoryManager = new MemoryManager({ + runtime, + tableName: ZX_MEMORY.price.tableName, + }); + + try { + const memories = await memoryManager.getMemories({ + roomId: message.roomId, + count: 1, + start: 0, + end: Date.now(), + }); + + if (memories?.[0]) { + return JSON.parse(memories[0].content.text) as PriceInquiry; + } + return null; + } catch (error) { + elizaLogger.error(`Failed to retrieve price inquiry: ${error.message}`); + return null; + } +}; + +export const storeQuoteToMemory = async ( + runtime: IAgentRuntime, + message: Memory, + quote: Quote +) => { + const memory: Memory = { + roomId: message.roomId, + userId: message.userId, + agentId: runtime.agentId, + content: { + text: JSON.stringify(quote), + type: ZX_MEMORY.quote.type, + }, + }; + + const memoryManager = new MemoryManager({ + runtime, + tableName: ZX_MEMORY.quote.tableName, + }); + + await memoryManager.createMemory(memory); +}; + +/** + * @returns example: + * 🛣️ Route: + * WETH → DAI → LINK + * • WETH → DAI: 100% via Uniswap_V3 + * • DAI → LINK: 14.99% via Uniswap_V3, 85.01% via Uniswap_V3 + */ + +export const formatRouteInfo = (quote: GetQuoteResponse): string[] => { + if (!quote.route.tokens || !quote.route.fills) { + return []; + } + // Get unique route path + const routeTokens = quote.route.tokens; + const routePath = routeTokens.map((t) => t.symbol).join(" → "); + + // Group fills by token pairs + const fillsByPair = quote.route.fills.reduce((acc, fill) => { + const key = `${fill.from}-${fill.to}`; + if (!acc[key]) acc[key] = []; + acc[key].push(fill); + return acc; + }, {} as Record); + + // Format each pair's route details + const routeDetails = Object.entries(fillsByPair).map(([pair, fills]) => { + const [fromAddr, toAddr] = pair.split("-"); + const from = routeTokens.find( + (t) => t.address.toLowerCase() === fromAddr.toLowerCase() + )?.symbol; + const to = routeTokens.find( + (t) => t.address.toLowerCase() === toAddr.toLowerCase() + )?.symbol; + + if (fills.length === 1) { + return ` • ${from} → ${to}: ${ + Number(fills[0].proportionBps) / 100 + }% via ${fills[0].source}`; + } + return [ + ` • ${from} → ${to}:`, + ...fills.map( + (f) => `${Number(f.proportionBps) / 100}% via ${f.source}` + ), + ].join(", "); + }); + + return ["🛣️ Route:", routePath, ...routeDetails]; +}; diff --git a/packages/plugin-0x/src/actions/swap.ts b/packages/plugin-0x/src/actions/swap.ts new file mode 100644 index 00000000000..68ead188e2a --- /dev/null +++ b/packages/plugin-0x/src/actions/swap.ts @@ -0,0 +1,188 @@ +import { + Action, + IAgentRuntime, + Memory, + State, + HandlerCallback, + elizaLogger, + MemoryManager, +} from "@elizaos/core"; +import { Hex, numberToHex, concat } from "viem"; +import { CHAIN_EXPLORERS, ZX_MEMORY } from "../constants"; +import { getWalletClient } from "../hooks.ts/useGetWalletClient"; +import { Quote } from "../types"; + +export const swap: Action = { + name: "EXECUTE_SWAP_0X", + similes: [ + "SWAP_TOKENS_0X", + "TOKEN_SWAP_0X", + "TRADE_TOKENS_0X", + "EXCHANGE_TOKENS_0X", + ], + suppressInitialMessage: true, + description: "Execute a token swap using 0x protocol", + validate: async (runtime: IAgentRuntime) => { + return ( + !!runtime.getSetting("ZERO_EX_API_KEY") && + !!runtime.getSetting("WALLET_PRIVATE_KEY") + ); + }, + handler: async ( + runtime: IAgentRuntime, + message: Memory, + state: State, + options: Record, + callback: HandlerCallback + ) => { + const latestQuote = await retrieveLatestQuote(runtime, message); + if (!latestQuote) { + callback({ + text: "Please provide me the details of the swap. E.g. convert 000.1 Weth to USDC on Ethereum chain", + }); + return; + } + + const { quote, chainId } = latestQuote; + + try { + const client = getWalletClient(chainId); // 1 for mainnet, or pass chainId + + // 1. Handle Permit2 signature + let signature: Hex | undefined; + if (quote.permit2?.eip712) { + signature = await client.signTypedData({ + account: client.account, + ...quote.permit2.eip712, + }); + + if (signature && quote.transaction?.data) { + const sigLengthHex = numberToHex(signature.length, { + size: 32, + }) as Hex; + quote.transaction.data = concat([ + quote.transaction.data as Hex, + sigLengthHex, + signature, + ]); + } + } + + const nonce = await client.getTransactionCount({ + address: (client.account as { address: `0x${string}` }).address, + }); + + const txHash = await client.sendTransaction({ + account: client.account, + chain: client.chain, + gas: !!quote?.transaction.gas + ? BigInt(quote?.transaction.gas) + : undefined, + to: quote?.transaction.to as `0x${string}`, + data: quote.transaction.data as `0x${string}`, + value: BigInt(quote.transaction.value), + gasPrice: !!quote?.transaction.gasPrice + ? BigInt(quote?.transaction.gasPrice) + : undefined, + nonce: nonce, + kzg: undefined, + }); + + // Wait for transaction confirmation + const receipt = await client.waitForTransactionReceipt({ + hash: txHash, + }); + + if (receipt.status === "success") { + callback({ + text: `✅ Swap executed successfully!\nView on Explorer: ${CHAIN_EXPLORERS[chainId]}/tx/${txHash}`, + content: { hash: txHash, status: "success" }, + }); + return true; + } else { + callback({ + text: `❌ Swap failed! Check transaction: ${CHAIN_EXPLORERS[chainId]}/tx/${txHash}`, + content: { hash: txHash, status: "failed" }, + }); + return false; + } + } catch (error) { + elizaLogger.error("Swap execution failed:", error); + callback({ + text: `❌ Failed to execute swap: ${error.message || error}`, + content: { error: error.message || String(error) }, + }); + return false; + } + }, + examples: [ + [ + { + user: "{{user1}}", + content: { + text: "I want to swap 1 ETH for USDC", + }, + }, + { + user: "{{agent}}", + content: { + text: "Let me get you a quote for that swap.", + action: "GET_INDICATE_PRICE_0X", + }, + }, + { + user: "{{user1}}", + content: { + text: "Get the quote for 1 ETH for USDC on Ethereum chain", + }, + }, + { + user: "{{agent}}", + content: { + text: "Let me get you the quotefor 1 ETH for USDC on Ethereum chain", + action: "GET_QUOTE_0X", + }, + }, + { + user: "{{user1}}", + content: { + text: "execute the swap", + }, + }, + { + user: "{{agent}}", + content: { + text: "Let me execute the swap for you.", + action: "EXECUTE_SWAP_0X", + }, + }, + ], + ], +}; + +export const retrieveLatestQuote = async ( + runtime: IAgentRuntime, + message: Memory +): Promise => { + const memoryManager = new MemoryManager({ + runtime, + tableName: ZX_MEMORY.quote.tableName, + }); + + try { + const memories = await memoryManager.getMemories({ + roomId: message.roomId, + count: 1, + start: 0, + end: Date.now(), + }); + + if (memories?.[0]) { + return JSON.parse(memories[0].content.text) as Quote; + } + return null; + } catch (error) { + elizaLogger.error(`Failed to retrieve quote: ${error.message}`); + return null; + } +}; diff --git a/packages/plugin-0x/src/constants.ts b/packages/plugin-0x/src/constants.ts new file mode 100644 index 00000000000..f51220a229a --- /dev/null +++ b/packages/plugin-0x/src/constants.ts @@ -0,0 +1,143 @@ +import { Chains, TokenMetadata } from "./types"; + +export const ZX_MEMORY = { + price: { + tableName: "0x_prices", + type: "price_inquiry", + }, + quote: { + tableName: "0x_quotes", + type: "quote", + }, +}; + +export const CHAIN_NAMES: Record = { + [Chains.ethereum]: "Ethereum", + [Chains.optimism]: "Optimism", + [Chains.bsc]: "BSC", + [Chains.polygon]: "Polygon", + [Chains.base]: "Base", + [Chains.arbitrum]: "Arbitrum", + [Chains.avalanche]: "Avalanche", + [Chains.linea]: "Linea", + [Chains.scroll]: "Scroll", + [Chains.blast]: "Blast", +} as const; + +export const CHAIN_EXPLORERS: Record = { + [Chains.ethereum]: "https://etherscan.io", + [Chains.optimism]: "https://optimistic.etherscan.io", + [Chains.bsc]: "https://bscscan.com", + [Chains.polygon]: "https://polygonscan.com", + [Chains.base]: "https://basescan.org", + [Chains.arbitrum]: "https://arbiscan.io", + [Chains.avalanche]: "https://snowtrace.io", + [Chains.linea]: "https://lineascan.build", + [Chains.scroll]: "https://scrollscan.com", + [Chains.blast]: "https://blastscan.io", +} as const; + +export const NATIVE_TOKEN_ADDRESS = + "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; +export const NATIVE_TOKENS: Record = { + [Chains.ethereum]: { + chainId: Chains.ethereum, + name: "Ethereum", + symbol: "ETH", + decimals: 18, + address: NATIVE_TOKEN_ADDRESS, + type: "NATIVE", + logoURI: + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png", + }, + [Chains.optimism]: { + chainId: Chains.optimism, + name: "Ethereum", + symbol: "ETH", + decimals: 18, + address: NATIVE_TOKEN_ADDRESS, + type: "NATIVE", + logoURI: + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/optimism/info/logo.png", + }, + [Chains.bsc]: { + chainId: Chains.bsc, + name: "BNB Chain", + symbol: "BNB", + decimals: 18, + address: NATIVE_TOKEN_ADDRESS, + type: "NATIVE", + logoURI: + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/binance/info/logo.png", + }, + [Chains.polygon]: { + chainId: Chains.polygon, + name: "Polygon", + symbol: "MATIC", + decimals: 18, + address: NATIVE_TOKEN_ADDRESS, + type: "NATIVE", + logoURI: + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/polygon/info/logo.png", + }, + [Chains.base]: { + chainId: Chains.base, + name: "Ethereum", + symbol: "ETH", + decimals: 18, + address: NATIVE_TOKEN_ADDRESS, + type: "NATIVE", + logoURI: + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/base/info/logo.png", + }, + [Chains.arbitrum]: { + chainId: Chains.arbitrum, + name: "Ethereum", + symbol: "ETH", + decimals: 18, + address: NATIVE_TOKEN_ADDRESS, + type: "NATIVE", + logoURI: + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/arbitrum/info/logo.png", + }, + [Chains.avalanche]: { + chainId: Chains.avalanche, + name: "Avalanche", + symbol: "AVAX", + decimals: 18, + address: NATIVE_TOKEN_ADDRESS, + type: "NATIVE", + logoURI: + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/avalanchec/info/logo.png", + }, + [Chains.linea]: { + chainId: Chains.linea, + name: "Ethereum", + symbol: "ETH", + decimals: 18, + address: NATIVE_TOKEN_ADDRESS, + type: "NATIVE", + logoURI: + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/linea/info/logo.png", + }, + [Chains.scroll]: { + chainId: Chains.scroll, + name: "Ethereum", + symbol: "ETH", + decimals: 18, + address: NATIVE_TOKEN_ADDRESS, + type: "NATIVE", + logoURI: + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/scroll/info/logo.png", + }, + [Chains.blast]: { + chainId: Chains.blast, + name: "Ethereum", + symbol: "ETH", + decimals: 18, + address: NATIVE_TOKEN_ADDRESS, + type: "NATIVE", + logoURI: + "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/blast/info/logo.png", + }, +}; diff --git a/packages/plugin-0x/src/hooks.ts/useGetWalletClient.ts b/packages/plugin-0x/src/hooks.ts/useGetWalletClient.ts new file mode 100644 index 00000000000..5bc7238bb3b --- /dev/null +++ b/packages/plugin-0x/src/hooks.ts/useGetWalletClient.ts @@ -0,0 +1,106 @@ +import { + createWalletClient, + http, + publicActions, + createTestClient, + WalletClient, + PublicClient, + walletActions, +} from "viem"; + +import { + arbitrum, + avalanche, + base, + blast, + bsc, + hardhat, + linea, + mainnet, + optimism, + polygon, + scroll, +} from "viem/chains"; +import { privateKeyToAccount } from "viem/accounts"; + +const CHAIN_CONFIG = { + 1: { + chain: mainnet, + rpcUrl: process.env.ETH_RPC_URL, + }, + 10: { + chain: optimism, + rpcUrl: process.env.OPTIMISM_RPC_URL, + }, + 56: { + chain: bsc, + rpcUrl: process.env.BSC_RPC_URL, + }, + 137: { + chain: polygon, + rpcUrl: process.env.POLYGON_RPC_URL, + }, + 8453: { + chain: base, + rpcUrl: process.env.BASE_RPC_URL, + }, + 42161: { + chain: arbitrum, + rpcUrl: process.env.ARBITRUM_RPC_URL, + }, + 43114: { + chain: avalanche, + rpcUrl: process.env.AVALANCHE_RPC_URL, + }, + 59144: { + chain: linea, + rpcUrl: process.env.LINEA_RPC_URL, + }, + 534352: { + chain: scroll, + rpcUrl: process.env.SCROLL_RPC_URL, + }, + 81457: { + chain: blast, + rpcUrl: process.env.BLAST_RPC_URL, + }, +} as const; + +export const getWalletClient = ( + chainId: number +): WalletClient & PublicClient => { + const rawPrivateKey = process.env.WALLET_PRIVATE_KEY; + if (!rawPrivateKey) { + throw new Error("Wallet private key is required"); + } + if (!/^(0x)?[0-9a-fA-F]{64}$/.test(rawPrivateKey)) { + throw new Error("Invalid private key format"); + } + const privateKey = rawPrivateKey.startsWith("0x") + ? (rawPrivateKey as `0x${string}`) + : (`0x${rawPrivateKey}` as `0x${string}`); + + const account = privateKeyToAccount(privateKey); + + if (process.env.NODE_ENV === "development") { + return createTestClient({ + chain: hardhat, + transport: http(), + mode: "hardhat", + account: privateKeyToAccount( + process.env.WALLET_PRIVATE_KEY as `0x${string}` + ), + }) + .extend(walletActions) + .extend(publicActions) as WalletClient & PublicClient; + } + + const config = CHAIN_CONFIG[chainId as keyof typeof CHAIN_CONFIG]; + if (!config) throw new Error(`Chain ID ${chainId} not supported by 0x`); + + return createWalletClient({ + chain: config.chain, + transport: http(config.rpcUrl), + account, + }).extend(publicActions) as WalletClient & PublicClient; +}; diff --git a/packages/plugin-0x/src/index.ts b/packages/plugin-0x/src/index.ts new file mode 100644 index 00000000000..f7f493eae20 --- /dev/null +++ b/packages/plugin-0x/src/index.ts @@ -0,0 +1,18 @@ +import { Plugin } from "@elizaos/core"; +import { getIndicativePrice } from "./actions/getIndicativePrice"; +import { getQuote } from "./actions/getQuote"; +import { swap } from "./actions/swap"; + +export const zxPlugin: Plugin = { + name: "0x", + description: "0x Plugin for Eliza", + actions: [ + getIndicativePrice, + getQuote, + swap, + ], + evaluators: [], + providers: [], +}; + +export default zxPlugin; diff --git a/packages/plugin-0x/src/templates.ts b/packages/plugin-0x/src/templates.ts new file mode 100644 index 00000000000..980a92aaa87 --- /dev/null +++ b/packages/plugin-0x/src/templates.ts @@ -0,0 +1,64 @@ +export const getIndicativePriceTemplate = ` + You are helping users get indicative prices for token swaps across different chains. + + Extract the following information: + - sellToken: The token the user wants to sell (e.g., ETH, WETH, USDC) + - buyToken: The token the user wants to receive (e.g., USDC, WETH, USDT) + - sellAmount: The amount of tokens to sell (numeric value only) + - chain: The blockchain network for the swap (e.g., ethereum, optimism, arbitrum, base) + + Return in JSON format: + { + "sellTokenSymbol": "", + "buyTokenSymbol": "", + "sellAmount": "" + "chain": {{supportedChains}} + } + + Examples: + "What's the price of 2 ETH in USDC on Optimism?" + { + sellTokenSymbol: "ETH", + buyTokenSymbol: "USDC", + sellAmount: 2, + chain: "optimism" + } + + "I want to swap 1000 USDC to WETH on Base" + { + sellTokenSymbol: "USDC", + buyTokenSymbol: "WETH", + sellAmount: 1000, + chain: "base" + } + + Notes: + - If the chain is not specified, assume it's "ethereum". + - If you are unsure, just return null for the missing fields. + + Recent conversation: + {{recentMessages}} +`; + +export const getQuoteTemplate = `Look at the recent conversation and extract the quote details. + +Extract: +- Which token the user wants to sell (sellToken) +- Which token the user wants to buy (buyToken) +- How much they want to sell (sellAmount) If amount is not specified, return null for sellAmount + +For example: +"I want to convert 5 WETH to USDC" -> { "sellToken": "WETH", "buyToken": "USDC", "sellAmount": "5" } +"Convert 100 LINK to USDC" -> { "sellToken": "LINK", "buyToken": "USDC", "sellAmount": "100" } +"How much DAI can I get for 100 USDC?" -> { "sellToken": "USDC", "buyToken": "DAI", "sellAmount": "100" } +"WETH/USDT price?" -> { "sellToken": "WETH", "buyToken": "USDT", "sellAmount": null } + +Return in JSON format: +{ + "sellToken": "", + "buyToken": "", + "sellAmount": "" +} + +Recent conversation: +{{recentMessages}}`; diff --git a/packages/plugin-0x/src/types.ts b/packages/plugin-0x/src/types.ts new file mode 100644 index 00000000000..20dd484c853 --- /dev/null +++ b/packages/plugin-0x/src/types.ts @@ -0,0 +1,225 @@ +export enum Chains { + arbitrum = 42161, + avalanche = 43114, + base = 8453, + bsc = 56, + blast = 81457, + ethereum = 1, + linea = 59144, + optimism = 10, + polygon = 137, + scroll = 534352, +} + +export interface SwapRequestParams { + chainId: string; // e.g., "1" for Ethereum mainnet + sellToken: string; // token address to sell + buyToken: string; // token address to buy + sellAmount: string; // amount in wei + taker: string; // wallet address + slippagePercentage?: string; // optional, e.g., "0.01" +} + +export interface GetIndicativePriceResponse { + chainId: number; + price: string; + buyAmount: string; + buyToken: string; + sellAmount: string; + sellToken: string; + blockNumber: string; + estimatedPriceImpact: string; + estimatedGas: string; + totalNetworkFee: string; + route: { + tokens: Array<{ + address: string; + symbol: string; + name: string; + decimals: number; + }>; + fills: Array<{ + source: string; + proportionBps: string; + from: string; + to: string; + }>; + }; + fees: { + zeroExFee: { + amount: string; + token: string; + type: "volume"; + } | null; + integratorFee: { + amount: string; + token: string; + type: "volume"; + } | null; + gasFee: { + amount: string; + token: string; + type: "volume"; + } | null; + }; + issues?: { + balance?: { + token: string; + actual: string; + expected: string; + }; + allowance?: { + token: string; + actual: string; + expected: string; + }; + }; + permit2: { + type: "Permit2"; + hash: string; + eip712: { + types: { + PermitTransferFrom: Array<{ name: string; type: string }>; + TokenPermissions: Array<{ name: string; type: string }>; + EIP712Domain: Array<{ name: string; type: string }>; + }; + domain: { + name: string; + chainId: number; + verifyingContract: string; + }; + message: { + permitted: { + token: string; + amount: string; + }; + spender: string; + nonce: string; + deadline: string; + }; + primaryType: string; + }; + }; +} + +export interface GetQuoteResponse { + blockNumber: string; + buyAmount: string; + buyToken: string; + sellAmount: string; + sellToken: string; + minBuyAmount: string; + liquidityAvailable: boolean; + totalNetworkFee: string; + zid: string; + fees: { + zeroExFee: { + amount: string; + token: string; + type: string; + } | null; + integratorFee: { + amount: string; + token: string; + type: string; + } | null; + gasFee: { + amount: string; + token: string; + type: string; + } | null; + }; + issues: { + allowance: null; + balance: { + token: string; + actual: string; + expected: string; + } | null; + simulationIncomplete: boolean; + invalidSourcesPassed: string[]; + }; + permit2: { + type: "Permit2"; + hash: string; + eip712: { + types: Record; + domain: Record; + message: Record; + primaryType: string; + }; + }; + route: { + fills: Array<{ + from: string; + to: string; + source: string; + proportionBps: string; + }>; + tokens: Array<{ + address: string; + symbol: string; + }>; + }; + tokenMetadata: { + buyToken: { + buyTaxBps: string; + sellTaxBps: string; + }; + sellToken: { + buyTaxBps: string; + sellTaxBps: string; + }; + }; + transaction: { + to: string; + data: string; + gas: string; + gasPrice: string; + value: string; + }; +} + +export interface TokenMetadata { + chainId: number; + address: string; + name: string; + symbol: string; + decimals: number; + logoURI?: string; + type: string; +} + +export interface TrustWalletTokenMetadata { + address: string; + name: string; + symbol: string; + decimals: number; + logoURI?: string; + type: string; + pairs: string[]; +} + +export interface TrustWalletGithubJson { + name: string; + logoURI: string; + timestamp: string; + tokens: TrustWalletTokenMetadata[]; +} + +export interface PriceInquiry { + sellTokenObject: TokenMetadata; + buyTokenObject: TokenMetadata; + sellAmountBaseUnits: string; + chainId: number; + timestamp: string; +} + +export interface Quote { + sellTokenObject: TokenMetadata; + buyTokenObject: TokenMetadata; + sellAmountBaseUnits: string; + chainId: number; + quote: GetQuoteResponse; + timestamp: string; +} diff --git a/packages/plugin-0x/src/utils.ts b/packages/plugin-0x/src/utils.ts new file mode 100644 index 00000000000..0cbd10c0ad2 --- /dev/null +++ b/packages/plugin-0x/src/utils.ts @@ -0,0 +1,26 @@ +import { formatUnits, Hash } from "viem"; +import { EVMTokenRegistry } from "./EVMtokenRegistry"; +import { IAgentRuntime } from "@elizaos/core"; + +/** + * Formats a token amount with its symbol + * @param amount The amount in base units (e.g., wei) + * @param address The token address + * @param chainId The chain ID (defaults to 1 for Ethereum mainnet) + * @returns Formatted string like "1.234567 USDC" + */ +export function formatTokenAmount( + amount: string, + address: string, + chainId: number = 1 +): string { + if (!amount) return "0"; + + const tokenRegistry = EVMTokenRegistry.getInstance(); + const token = tokenRegistry.getTokenByAddress(address, chainId); + + if (!token) throw new Error(`Token not found for address: ${address}`); + + const parsedAmount = formatUnits(BigInt(amount), token.decimals); + return `${Number(parsedAmount).toFixed(4)} ${token.symbol}`; +} diff --git a/packages/plugin-0x/tsconfig.json b/packages/plugin-0x/tsconfig.json new file mode 100644 index 00000000000..74ac4ce5bb7 --- /dev/null +++ b/packages/plugin-0x/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../core/tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": ".", + "types": [ + "node" + ] + }, + "include": [ + "src/**/*.ts" + ] +} \ No newline at end of file diff --git a/packages/plugin-0x/tsup.config.ts b/packages/plugin-0x/tsup.config.ts new file mode 100644 index 00000000000..61b3ab19b13 --- /dev/null +++ b/packages/plugin-0x/tsup.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + outDir: "dist", + sourcemap: true, + clean: true, + format: ["esm"], // Ensure you're targeting CommonJS + external: ["dotenv", "fs", "path", "https", "http"], +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e5092c1ca5c..9745e3a24e7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -966,7 +966,7 @@ importers: version: link:../core '@lens-protocol/client': specifier: 2.2.0 - version: 2.2.0(@jest/globals@29.7.0)(@lens-protocol/metadata@1.2.0(zod@3.23.8))(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10) + version: 2.2.0(@jest/globals@29.7.0)(@lens-protocol/metadata@1.2.0(zod@3.23.8))(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ioredis@5.4.2)(react@19.0.0)(utf-8-validate@5.0.10) '@lens-protocol/metadata': specifier: 1.2.0 version: 1.2.0(zod@3.23.8) @@ -1304,6 +1304,22 @@ importers: specifier: 8.3.5 version: 8.3.5(@swc/core@1.10.8(@swc/helpers@0.5.15))(jiti@2.4.2)(postcss@8.5.1)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0) + packages/plugin-0x: + dependencies: + '@0x/swap-ts-sdk': + specifier: 2.1.1 + version: 2.1.1(@types/express@5.0.0)(@types/node@22.10.7)(encoding@0.1.13) + '@elizaos/core': + specifier: workspace:* + version: link:../core + zod: + specifier: ^3.22.4 + version: 3.23.8 + devDependencies: + tsup: + specifier: ^8.0.1 + version: 8.3.5(@swc/core@1.10.8(@swc/helpers@0.5.15))(jiti@2.4.2)(postcss@8.5.1)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0) + packages/plugin-3d-generation: dependencies: '@elizaos/core': @@ -3631,6 +3647,25 @@ packages: graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 typescript: ^5.0.0 + '@0x/contract-addresses@8.13.0': + resolution: {integrity: sha512-wWqDSPYZOu2YNDRXdIY5pfzel+w9jM3DBNjVT8o9+wdySY0X09kxHVwazIi4QL4Fa79HLN86KY5sXlfhXNBG9w==} + engines: {node: '>=6.12'} + + '@0x/swap-ts-sdk@2.1.1': + resolution: {integrity: sha512-SbfmvtDTAeP3SDmBdZ1TKKTrbsFTiorFy3STeYj+OXDN0TtVfXLfhAYrIQiHYv30F9cSZZSNv993ldVcHociOw==} + + '@0x/types@3.3.7': + resolution: {integrity: sha512-6lPXPnvKaIfAJ5hIgs81SytqNCPCLstQ/DA598iLpb90KKjjz8QsdrfII4JeKdrEREvLcWSH9SeH4sNPWyLhlA==} + engines: {node: '>=6.12'} + + '@0x/typescript-typings@5.3.2': + resolution: {integrity: sha512-VIo8PS/IRXrI1aEzM8TenUMViX4MFMKBnIAwqC4K/ewVDSnKyYZSk8fzw0XZph6tN07obchPf+1sHIWYe8EUow==} + engines: {node: '>=6.12'} + + '@0x/utils@7.0.0': + resolution: {integrity: sha512-g+Bp0eHUGhnVGeVZqGn7UVtpzs/FuoXksiDaajfJrHFW0owwo5YwpwFIAVU7/ca0B6IKa74e71gskLwWGINEFg==} + engines: {node: '>=6.12'} + '@0xsquid/sdk@2.8.29': resolution: {integrity: sha512-u8oJ67sN9rkc1VMoCuTYyNlSUxFrp5SXnium8YASii0NKuK+42uTUn5T+4gFKh529ZzChJTYgTXLVWk4Vja8Kg==} @@ -7056,6 +7091,9 @@ packages: engines: {node: '>=6'} hasBin: true + '@hapi/bourne@3.0.0': + resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==} + '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -10825,6 +10863,14 @@ packages: resolution: {integrity: sha512-tuwHtoYzvqnahsMrecfNNkQceCYwgiY0qKS8RwqtaxvDEgjm0E+0bXwKz2eUD3ZFYifomJmRKDmSBx9yQzAeMQ==} engines: {node: '>=20.18.0'} + '@trpc/client@10.40.0': + resolution: {integrity: sha512-bT6BcdWjj0KzGQiimE6rB2tIaRYX0Ear4Gthb5szN/c01wrP0yC1Fbz2uCcm/QTVAwu4Lve5M+YjPoEaTHG6lg==} + peerDependencies: + '@trpc/server': 10.40.0 + + '@trpc/server@10.40.0': + resolution: {integrity: sha512-49SUOMWzSZtu5+OdrADmJD+u+sjSE0qj1cWgYk2FY4jLkPJunLuNRuhzM7aOeBhiUjyfhg2YTfur8FN1WBmvEw==} + '@trysound/sax@0.2.0': resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -11185,6 +11231,9 @@ packages: '@types/mocha@10.0.10': resolution: {integrity: sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==} + '@types/mocha@5.2.7': + resolution: {integrity: sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==} + '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} @@ -11203,6 +11252,9 @@ packages: '@types/node@11.11.6': resolution: {integrity: sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==} + '@types/node@12.12.54': + resolution: {integrity: sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w==} + '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} @@ -12091,6 +12143,9 @@ packages: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} + abortcontroller-polyfill@1.7.8: + resolution: {integrity: sha512-9f1iZ2uWh92VcrU9Y8x+LdM4DLj75VE0MJB8zuF1iUnroEptStw+DQ8EQPMUdfe5k+PkB1uUfDQfWbhstH8LrQ==} + abs@1.3.14: resolution: {integrity: sha512-PrS26IzwKLWwuURpiKl8wRmJ2KdR/azaVrLEBWG/TALwT20Y7qjtYp1qcMLHA4206hBHY5phv3w4pjf9NPv4Vw==} @@ -12813,6 +12868,9 @@ packages: resolution: {integrity: sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==} engines: {node: '>= 10.0.0'} + bignumber.js@9.0.2: + resolution: {integrity: sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==} + bignumber.js@9.1.2: resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} @@ -13530,6 +13588,10 @@ packages: resolution: {integrity: sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + co-body@6.2.0: + resolution: {integrity: sha512-Kbpv2Yd1NdL1V/V4cwLVxraHDV6K8ayohr2rmH0J87Er8+zJjcTa6dAn9QMPC9CRgU8+aNajKbSf1TzDB1yKPA==} + engines: {node: '>=8.0.0'} + co@4.6.0: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -14590,6 +14652,9 @@ packages: detect-node-es@1.1.0: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + detect-node@2.0.3: + resolution: {integrity: sha512-64uDTOK+fKEa6XoSbkkDoeAX8Ep1XhwxwZtL1aw1En5p5UOK/ekJoFqd5BB1o+uOvF1iHVv6qDUxdOQ/VgWEQg==} + detect-node@2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} @@ -15273,6 +15338,10 @@ packages: resolution: {integrity: sha512-Ij7U9OgVZc4MAui8BttPCEaWUrAXy+eo2IbVfIxZyfzfFxMQrbIWXRUbrsRBqRrIhJ75T8P+KQRKpKTaG0Du8Q==} engines: {node: ^14.21.3 || >=16, npm: '>=9'} + ethereum-types@3.7.1: + resolution: {integrity: sha512-EBQwTGnGZQ9oHK7Za3DFEOxiElksRCoZECkk418vHiE2d59lLSejDZ1hzRVphtFjAu5YqONz4/XuAYdMBg+gWA==} + engines: {node: '>=6.12'} + ethereumjs-abi@0.6.8: resolution: {integrity: sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==} deprecated: This library has been deprecated and usage is discouraged. @@ -15290,6 +15359,9 @@ packages: peerDependencies: lodash: ^4.17.0 + ethers@4.0.49: + resolution: {integrity: sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==} + ethers@5.7.2: resolution: {integrity: sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==} @@ -16262,6 +16334,9 @@ packages: resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} engines: {node: '>=4'} + hash.js@1.1.3: + resolution: {integrity: sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==} + hash.js@1.1.7: resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} @@ -16610,6 +16685,10 @@ packages: resolution: {integrity: sha512-uyH0zfr1erU1OohLk0fT4Rrb94AOhguWNOcD9uGrSpRvNB+6gZXUoJX5J0NtvzBO10YZ9PgvA4NFgt+fYg8ojw==} engines: {node: '>=12'} + inflation@2.1.0: + resolution: {integrity: sha512-t54PPJHG1Pp7VQvxyVCJ9mBbjG3Hqryges9bXoOO6GExCPa+//i/d5GSuFtpx3ALLd7lgIAur6zrIlBQyJuMlQ==} + engines: {node: '>= 0.8.0'} + inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. @@ -17351,6 +17430,12 @@ packages: js-sha256@0.9.0: resolution: {integrity: sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==} + js-sha3@0.5.7: + resolution: {integrity: sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==} + + js-sha3@0.7.0: + resolution: {integrity: sha512-Wpks3yBDm0UcL5qlVhwW9Jr9n9i4FfeWBFOOXP5puDS/SiudJGhw7DPyBqn3487qD4F0lsC0q3zxink37f7zeA==} + js-sha3@0.8.0: resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} @@ -18964,6 +19049,18 @@ packages: node-machine-id@1.1.12: resolution: {integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==} + node-mocks-http@1.16.2: + resolution: {integrity: sha512-2Sh6YItRp1oqewZNlck3LaFp5vbyW2u51HX2p1VLxQ9U/bG90XV8JY9O7Nk+HDd6OOn/oV3nA5Tx5k4Rki0qlg==} + engines: {node: '>=14'} + peerDependencies: + '@types/express': ^4.17.21 || ^5.0.0 + '@types/node': '*' + peerDependenciesMeta: + '@types/express': + optional: true + '@types/node': + optional: true + node-releases@2.0.19: resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} @@ -19884,6 +19981,10 @@ packages: poly1305-js@0.4.4: resolution: {integrity: sha512-5B6/S+vg5AOr66wJDkh5LOpU/F3EKANDy4VXKsNZLXea1uCy6CiOWOZ3VhcC0nYdhE7vJUMcLxqcVlrv2g/+Rg==} + popper.js@1.14.3: + resolution: {integrity: sha512-3lmujhsHXzb83+sI0PzfrE3O1XHZG8m8MXNMTupvA6LrM1/nnsiqYaacYc/RIente9VqnTDPztGEM8uvPAMGyg==} + deprecated: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1 + portfinder@1.0.32: resolution: {integrity: sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==} engines: {node: '>= 0.12.0'} @@ -21634,6 +21735,9 @@ packages: resolution: {integrity: sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==} engines: {node: '>= 10.13.0'} + scrypt-js@2.0.4: + resolution: {integrity: sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==} + scrypt-js@3.0.1: resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} @@ -21756,6 +21860,9 @@ packages: resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} engines: {node: '>= 0.4'} + setimmediate@1.0.4: + resolution: {integrity: sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog==} + setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} @@ -22942,6 +23049,12 @@ packages: trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + trpc-openapi@1.2.0: + resolution: {integrity: sha512-pfYoCd/3KYXWXvUPZBKJw455OOwngKN/6SIcj7Yit19OMLJ+8yVZkEvGEeg5wUSwfsiTdRsKuvqkRPXVSwV7ew==} + peerDependencies: + '@trpc/server': ^10.0.0 + zod: ^3.14.4 + ts-api-utils@1.4.3: resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} engines: {node: '>=16'} @@ -23739,6 +23852,10 @@ packages: resolution: {integrity: sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==} hasBin: true + uuid@2.0.1: + resolution: {integrity: sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + uuid@3.4.0: resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. @@ -24641,6 +24758,10 @@ packages: resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==} engines: {node: '>=0.4.0'} + xmlhttprequest@1.8.0: + resolution: {integrity: sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==} + engines: {node: '>=0.4.0'} + xsalsa20@1.2.0: resolution: {integrity: sha512-FIr/DEeoHfj7ftfylnoFt3rAIRoWXpx2AoDfrT2qD2wtp7Dp+COajvs/Icb7uHqRW9m60f5iXZwdsJJO3kvb7w==} @@ -24763,6 +24884,9 @@ packages: peerDependencies: zod: ^3.24.1 + zod@3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} @@ -24817,6 +24941,55 @@ snapshots: graphql: 16.10.0 typescript: 5.7.3 + '@0x/contract-addresses@8.13.0': {} + + '@0x/swap-ts-sdk@2.1.1(@types/express@5.0.0)(@types/node@22.10.7)(encoding@0.1.13)': + dependencies: + '@0x/contract-addresses': 8.13.0 + '@0x/utils': 7.0.0(encoding@0.1.13) + '@trpc/client': 10.40.0(@trpc/server@10.40.0) + '@trpc/server': 10.40.0 + trpc-openapi: 1.2.0(@trpc/server@10.40.0)(@types/express@5.0.0)(@types/node@22.10.7)(zod@3.22.4) + zod: 3.22.4 + transitivePeerDependencies: + - '@types/express' + - '@types/node' + - encoding + + '@0x/types@3.3.7': + dependencies: + '@types/node': 12.12.54 + bignumber.js: 9.0.2 + ethereum-types: 3.7.1 + + '@0x/typescript-typings@5.3.2': + dependencies: + '@types/bn.js': 4.11.6 + '@types/node': 12.12.54 + '@types/react': 19.0.7 + bignumber.js: 9.0.2 + ethereum-types: 3.7.1 + popper.js: 1.14.3 + + '@0x/utils@7.0.0(encoding@0.1.13)': + dependencies: + '@0x/types': 3.3.7 + '@0x/typescript-typings': 5.3.2 + '@types/mocha': 5.2.7 + '@types/node': 12.12.54 + abortcontroller-polyfill: 1.7.8 + bignumber.js: 9.0.2 + chalk: 2.4.2 + detect-node: 2.0.3 + ethereum-types: 3.7.1 + ethereumjs-util: 7.1.5 + ethers: 4.0.49 + isomorphic-fetch: 3.0.0(encoding@0.1.13) + js-sha3: 0.7.0 + lodash: 4.17.21 + transitivePeerDependencies: + - encoding + '@0xsquid/sdk@2.8.29(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10)': dependencies: '@cosmjs/cosmwasm-stargate': 0.32.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) @@ -30672,6 +30845,8 @@ snapshots: protobufjs: 7.4.0 yargs: 17.7.2 + '@hapi/bourne@3.0.0': {} + '@hapi/hoek@9.3.0': {} '@hapi/topo@5.1.0': @@ -31956,7 +32131,7 @@ snapshots: - utf-8-validate - wait-for-expect - '@lens-protocol/client@2.2.0(@jest/globals@29.7.0)(@lens-protocol/metadata@1.2.0(zod@3.23.8))(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)': + '@lens-protocol/client@2.2.0(@jest/globals@29.7.0)(@lens-protocol/metadata@1.2.0(zod@3.23.8))(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ioredis@5.4.2)(react@19.0.0)(utf-8-validate@5.0.10)': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/abstract-signer': 5.7.0 @@ -31967,7 +32142,7 @@ snapshots: '@ethersproject/providers': 5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@ethersproject/wallet': 5.7.0 '@lens-protocol/blockchain-bindings': 0.10.2(@jest/globals@29.7.0)(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@lens-protocol/gated-content': 0.5.1(@ethersproject/abi@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ethersproject/wallet@5.7.0)(@lens-protocol/metadata@1.2.0(zod@3.23.8))(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)(zod@3.23.8) + '@lens-protocol/gated-content': 0.5.1(@ethersproject/abi@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ethersproject/wallet@5.7.0)(@lens-protocol/metadata@1.2.0(zod@3.23.8))(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ioredis@5.4.2)(react@19.0.0)(utf-8-validate@5.0.10)(zod@3.23.8) '@lens-protocol/shared-kernel': 0.12.0 '@lens-protocol/storage': 0.8.1 graphql: 16.10.0 @@ -32016,7 +32191,7 @@ snapshots: optionalDependencies: '@jest/globals': 29.7.0 - '@lens-protocol/gated-content@0.5.1(@ethersproject/abi@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ethersproject/wallet@5.7.0)(@lens-protocol/metadata@1.2.0(zod@3.23.8))(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))(react@19.0.0)(utf-8-validate@5.0.10)(zod@3.23.8)': + '@lens-protocol/gated-content@0.5.1(@ethersproject/abi@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ethersproject/wallet@5.7.0)(@lens-protocol/metadata@1.2.0(zod@3.23.8))(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ioredis@5.4.2)(react@19.0.0)(utf-8-validate@5.0.10)(zod@3.23.8)': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/address': 5.7.0 @@ -32031,7 +32206,7 @@ snapshots: '@lit-protocol/constants': 2.1.62 '@lit-protocol/crypto': 2.1.62(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@lit-protocol/encryption': 2.1.62(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@lit-protocol/node-client': 2.1.62(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ethersproject/wallet@5.7.0)(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.0.0)(utf-8-validate@5.0.10) + '@lit-protocol/node-client': 2.1.62(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ethersproject/wallet@5.7.0)(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.4.2)(react@19.0.0)(utf-8-validate@5.0.10) '@lit-protocol/types': 2.1.62 siwe: 2.3.2(ethers@6.13.5(bufferutil@4.0.9)(utf-8-validate@5.0.10)) tslib: 2.8.1 @@ -32244,14 +32419,14 @@ snapshots: - bufferutil - utf-8-validate - '@lit-protocol/auth-browser@2.1.62(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ethersproject/wallet@5.7.0)(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.0.0)(utf-8-validate@5.0.10)': + '@lit-protocol/auth-browser@2.1.62(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ethersproject/wallet@5.7.0)(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.4.2)(react@19.0.0)(utf-8-validate@5.0.10)': dependencies: '@lit-protocol/constants': 2.1.62 '@lit-protocol/misc': 2.1.62 '@lit-protocol/misc-browser': 2.1.62(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@lit-protocol/types': 2.1.62 '@lit-protocol/uint8arrays': 2.1.62 - '@walletconnect/ethereum-provider': 2.17.4(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.0.0)(utf-8-validate@5.0.10) + '@walletconnect/ethereum-provider': 2.17.4(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.4.2)(react@19.0.0)(utf-8-validate@5.0.10) ethers: 5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) lit-connect-modal: 0.1.11 lit-siwe: 1.1.8(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ethersproject/wallet@5.7.0) @@ -32352,10 +32527,10 @@ snapshots: '@lit-protocol/nacl@2.1.62': {} - '@lit-protocol/node-client@2.1.62(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ethersproject/wallet@5.7.0)(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.0.0)(utf-8-validate@5.0.10)': + '@lit-protocol/node-client@2.1.62(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ethersproject/wallet@5.7.0)(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.4.2)(react@19.0.0)(utf-8-validate@5.0.10)': dependencies: '@lit-protocol/access-control-conditions': 2.1.62(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@lit-protocol/auth-browser': 2.1.62(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ethersproject/wallet@5.7.0)(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.0.0)(utf-8-validate@5.0.10) + '@lit-protocol/auth-browser': 2.1.62(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))(@ethersproject/wallet@5.7.0)(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.4.2)(react@19.0.0)(utf-8-validate@5.0.10) '@lit-protocol/bls-sdk': 2.1.62 '@lit-protocol/constants': 2.1.62 '@lit-protocol/crypto': 2.1.62(bufferutil@4.0.9)(utf-8-validate@5.0.10) @@ -32367,7 +32542,7 @@ snapshots: '@lit-protocol/nacl': 2.1.62 '@lit-protocol/types': 2.1.62 '@lit-protocol/uint8arrays': 2.1.62 - '@walletconnect/ethereum-provider': 2.17.4(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.0.0)(utf-8-validate@5.0.10) + '@walletconnect/ethereum-provider': 2.17.4(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.4.2)(react@19.0.0)(utf-8-validate@5.0.10) ethers: 5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10) jszip: 3.10.1 lit-connect-modal: 0.1.11 @@ -38207,6 +38382,12 @@ snapshots: dependencies: '@grpc/grpc-js': 1.12.5 + '@trpc/client@10.40.0(@trpc/server@10.40.0)': + dependencies: + '@trpc/server': 10.40.0 + + '@trpc/server@10.40.0': {} + '@trysound/sax@0.2.0': {} '@ts-morph/common@0.19.0': @@ -38629,6 +38810,8 @@ snapshots: '@types/mocha@10.0.10': {} + '@types/mocha@5.2.7': {} + '@types/ms@2.1.0': {} '@types/multer@1.4.12': @@ -38648,6 +38831,8 @@ snapshots: '@types/node@11.11.6': {} + '@types/node@12.12.54': {} + '@types/node@12.20.55': {} '@types/node@17.0.45': {} @@ -39772,13 +39957,13 @@ snapshots: - uploadthing - utf-8-validate - '@walletconnect/core@2.17.4(bufferutil@4.0.9)(ioredis@5.4.2)(utf-8-validate@6.0.5)': + '@walletconnect/core@2.17.4(bufferutil@4.0.9)(ioredis@5.4.2)(utf-8-validate@5.0.10)': dependencies: '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@6.0.5) + '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@walletconnect/keyvaluestorage': 1.1.1(ioredis@5.4.2) '@walletconnect/logger': 2.1.2 '@walletconnect/relay-api': 1.0.11 @@ -39813,13 +39998,13 @@ snapshots: - uploadthing - utf-8-validate - '@walletconnect/core@2.17.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)': + '@walletconnect/core@2.17.4(bufferutil@4.0.9)(ioredis@5.4.2)(utf-8-validate@6.0.5)': dependencies: '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@6.0.5) '@walletconnect/keyvaluestorage': 1.1.1(ioredis@5.4.2) '@walletconnect/logger': 2.1.2 '@walletconnect/relay-api': 1.0.11 @@ -39896,7 +40081,7 @@ snapshots: - uploadthing - utf-8-validate - '@walletconnect/ethereum-provider@2.17.4(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.0.0)(utf-8-validate@5.0.10)': + '@walletconnect/ethereum-provider@2.17.4(@types/react@19.0.7)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.4.2)(react@19.0.0)(utf-8-validate@5.0.10)': dependencies: '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) '@walletconnect/jsonrpc-provider': 1.0.14 @@ -39904,9 +40089,9 @@ snapshots: '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/keyvaluestorage': 1.1.1(ioredis@5.4.2) '@walletconnect/modal': 2.7.0(@types/react@19.0.7)(react@19.0.0) - '@walletconnect/sign-client': 2.17.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@walletconnect/sign-client': 2.17.4(bufferutil@4.0.9)(ioredis@5.4.2)(utf-8-validate@5.0.10) '@walletconnect/types': 2.17.4(ioredis@5.4.2) - '@walletconnect/universal-provider': 2.17.4(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) + '@walletconnect/universal-provider': 2.17.4(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.4.2)(utf-8-validate@5.0.10) '@walletconnect/utils': 2.17.4(ioredis@5.4.2) events: 3.3.0 transitivePeerDependencies: @@ -40095,9 +40280,9 @@ snapshots: - uploadthing - utf-8-validate - '@walletconnect/sign-client@2.17.4(bufferutil@4.0.9)(ioredis@5.4.2)(utf-8-validate@6.0.5)': + '@walletconnect/sign-client@2.17.4(bufferutil@4.0.9)(ioredis@5.4.2)(utf-8-validate@5.0.10)': dependencies: - '@walletconnect/core': 2.17.4(bufferutil@4.0.9)(ioredis@5.4.2)(utf-8-validate@6.0.5) + '@walletconnect/core': 2.17.4(bufferutil@4.0.9)(ioredis@5.4.2)(utf-8-validate@5.0.10) '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-utils': 1.0.8 @@ -40128,9 +40313,9 @@ snapshots: - uploadthing - utf-8-validate - '@walletconnect/sign-client@2.17.4(bufferutil@4.0.9)(utf-8-validate@5.0.10)': + '@walletconnect/sign-client@2.17.4(bufferutil@4.0.9)(ioredis@5.4.2)(utf-8-validate@6.0.5)': dependencies: - '@walletconnect/core': 2.17.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@walletconnect/core': 2.17.4(bufferutil@4.0.9)(ioredis@5.4.2)(utf-8-validate@6.0.5) '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-utils': 1.0.8 @@ -40258,7 +40443,7 @@ snapshots: - uploadthing - utf-8-validate - '@walletconnect/universal-provider@2.17.4(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10)': + '@walletconnect/universal-provider@2.17.4(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.4.2)(utf-8-validate@5.0.10)': dependencies: '@walletconnect/events': 1.0.1 '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) @@ -40267,7 +40452,7 @@ snapshots: '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/keyvaluestorage': 1.1.1(ioredis@5.4.2) '@walletconnect/logger': 2.1.2 - '@walletconnect/sign-client': 2.17.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@walletconnect/sign-client': 2.17.4(bufferutil@4.0.9)(ioredis@5.4.2)(utf-8-validate@5.0.10) '@walletconnect/types': 2.17.4(ioredis@5.4.2) '@walletconnect/utils': 2.17.4(ioredis@5.4.2) events: 3.3.0 @@ -40561,6 +40746,8 @@ snapshots: dependencies: event-target-shim: 5.0.1 + abortcontroller-polyfill@1.7.8: {} + abs@1.3.14: dependencies: ul: 5.2.15 @@ -41539,6 +41726,8 @@ snapshots: dependencies: bindings: 1.5.0 + bignumber.js@9.0.2: {} + bignumber.js@9.1.2: {} bignumber@1.1.0: {} @@ -42479,6 +42668,14 @@ snapshots: cmd-shim@6.0.3: {} + co-body@6.2.0: + dependencies: + '@hapi/bourne': 3.0.0 + inflation: 2.1.0 + qs: 6.14.0 + raw-body: 2.5.2 + type-is: 1.6.18 + co@4.6.0: {} code-block-writer@12.0.0: {} @@ -43659,6 +43856,8 @@ snapshots: detect-node-es@1.1.0: {} + detect-node@2.0.3: {} + detect-node@2.1.0: {} detect-port-alt@1.1.6: @@ -44788,6 +44987,11 @@ snapshots: '@scure/bip32': 1.5.0 '@scure/bip39': 1.4.0 + ethereum-types@3.7.1: + dependencies: + '@types/node': 12.12.54 + bignumber.js: 9.0.2 + ethereumjs-abi@0.6.8: dependencies: bn.js: 4.12.1 @@ -44819,6 +45023,18 @@ snapshots: - bufferutil - utf-8-validate + ethers@4.0.49: + dependencies: + aes-js: 3.0.0 + bn.js: 4.12.1 + elliptic: 6.5.4 + hash.js: 1.1.3 + js-sha3: 0.5.7 + scrypt-js: 2.0.4 + setimmediate: 1.0.4 + uuid: 2.0.1 + xmlhttprequest: 1.8.0 + ethers@5.7.2(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: '@ethersproject/abi': 5.7.0 @@ -46235,6 +46451,11 @@ snapshots: readable-stream: 3.6.2 safe-buffer: 5.2.1 + hash.js@1.1.3: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + hash.js@1.1.7: dependencies: inherits: 2.0.4 @@ -46720,6 +46941,8 @@ snapshots: infima@0.2.0-alpha.45: {} + inflation@2.1.0: {} + inflight@1.0.6: dependencies: once: 1.4.0 @@ -47890,6 +48113,10 @@ snapshots: js-sha256@0.9.0: {} + js-sha3@0.5.7: {} + + js-sha3@0.7.0: {} + js-sha3@0.8.0: {} js-sha512@0.8.0: {} @@ -50088,6 +50315,22 @@ snapshots: node-machine-id@1.1.12: {} + node-mocks-http@1.16.2(@types/express@5.0.0)(@types/node@22.10.7): + dependencies: + accepts: 1.3.8 + content-disposition: 0.5.4 + depd: 1.1.2 + fresh: 0.5.2 + merge-descriptors: 1.0.3 + methods: 1.1.2 + mime: 1.6.0 + parseurl: 1.3.3 + range-parser: 1.2.1 + type-is: 1.6.18 + optionalDependencies: + '@types/express': 5.0.0 + '@types/node': 22.10.7 + node-releases@2.0.19: {} node-status-codes@1.0.0: {} @@ -51356,6 +51599,8 @@ snapshots: dependencies: big-integer: 1.6.52 + popper.js@1.14.3: {} + portfinder@1.0.32: dependencies: async: 2.6.4 @@ -53371,6 +53616,8 @@ snapshots: ajv-formats: 2.1.1(ajv@8.17.1) ajv-keywords: 5.1.0(ajv@8.17.1) + scrypt-js@2.0.4: {} + scrypt-js@3.0.1: {} scryptsy@2.1.0: {} @@ -53524,6 +53771,8 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.1.1 + setimmediate@1.0.4: {} + setimmediate@1.0.5: {} setprototypeof@1.1.0: {} @@ -55044,6 +55293,20 @@ snapshots: trough@2.2.0: {} + trpc-openapi@1.2.0(@trpc/server@10.40.0)(@types/express@5.0.0)(@types/node@22.10.7)(zod@3.22.4): + dependencies: + '@trpc/server': 10.40.0 + co-body: 6.2.0 + h3: 1.13.1 + lodash.clonedeep: 4.5.0 + node-mocks-http: 1.16.2(@types/express@5.0.0)(@types/node@22.10.7) + openapi-types: 12.1.3 + zod: 3.22.4 + zod-to-json-schema: 3.24.1(zod@3.22.4) + transitivePeerDependencies: + - '@types/express' + - '@types/node' + ts-api-utils@1.4.3(typescript@5.6.3): dependencies: typescript: 5.6.3 @@ -56002,6 +56265,8 @@ snapshots: uuid@11.0.5: {} + uuid@2.0.1: {} + uuid@3.4.0: {} uuid@8.3.2: {} @@ -57883,6 +58148,8 @@ snapshots: xmlhttprequest-ssl@2.1.2: {} + xmlhttprequest@1.8.0: {} + xsalsa20@1.2.0: {} xstream@11.14.0: @@ -58007,6 +58274,10 @@ snapshots: zlibjs@0.3.1: {} + zod-to-json-schema@3.24.1(zod@3.22.4): + dependencies: + zod: 3.22.4 + zod-to-json-schema@3.24.1(zod@3.23.8): dependencies: zod: 3.23.8 @@ -58015,6 +58286,8 @@ snapshots: dependencies: zod: 3.24.1 + zod@3.22.4: {} + zod@3.23.8: {} zod@3.24.1: {}