UNPKG

@eco-foundation/routes-ts

Version:

The Eco Routes Protocol is a decentralized intent based system that allows users to submit their intent to the network and have it fulfilled by a solver on the destination rollup of their choise.

281 lines (280 loc) 10.8 kB
"use strict"; /** * @file intent.ts * * Intent-related utilities for Eco Routes protocol. * * This file provides type-safe functions for encoding, decoding, and hashing * protocol intent structures. It extracts the necessary type information directly * from the contract ABI, ensuring that any contract changes that affect intent * structures will be caught at compile time. * * Key features: * - Type-safe encoding and decoding of Route and Reward structures * - Intent hashing functions that match the on-chain implementations * - TypeScript types derived directly from contract ABI */ Object.defineProperty(exports, "__esModule", { value: true }); exports.hashIntent = exports.hashReward = exports.hashRoute = exports.decodeIntent = exports.encodeIntent = exports.decodeReward = exports.encodeReward = exports.decodeRoute = exports.encodeRoute = exports.IntentAbi = exports.RewardAbi = exports.RouteAbi = void 0; const viem_1 = require("viem"); // Define the ABI structures directly based on the Portal contract // This avoids complex type extraction that can fail with TypeScript /** * Route struct ABI definition */ exports.RouteAbi = [ { internalType: 'bytes32', name: 'salt', type: 'bytes32' }, { internalType: 'uint64', name: 'deadline', type: 'uint64' }, { internalType: 'address', name: 'portal', type: 'address' }, { internalType: 'uint256', name: 'nativeAmount', type: 'uint256' }, { components: [ { internalType: 'address', name: 'token', type: 'address' }, { internalType: 'uint256', name: 'amount', type: 'uint256' }, ], internalType: 'struct TokenAmount[]', name: 'tokens', type: 'tuple[]', }, { components: [ { internalType: 'address', name: 'target', type: 'address' }, { internalType: 'bytes', name: 'data', type: 'bytes' }, { internalType: 'uint256', name: 'value', type: 'uint256' }, ], internalType: 'struct Call[]', name: 'calls', type: 'tuple[]', }, ]; /** * Reward struct ABI definition */ exports.RewardAbi = [ { internalType: 'uint64', name: 'deadline', type: 'uint64' }, { internalType: 'address', name: 'creator', type: 'address' }, { internalType: 'address', name: 'prover', type: 'address' }, { internalType: 'uint256', name: 'nativeAmount', type: 'uint256' }, { components: [ { internalType: 'address', name: 'token', type: 'address' }, { internalType: 'uint256', name: 'amount', type: 'uint256' }, ], internalType: 'struct TokenAmount[]', name: 'tokens', type: 'tuple[]', }, ]; /** * Intent struct ABI definition */ exports.IntentAbi = [ { internalType: 'uint64', name: 'destination', type: 'uint64' }, { components: exports.RouteAbi, internalType: 'struct Route', name: 'route', type: 'tuple', }, { components: exports.RewardAbi, internalType: 'struct Reward', name: 'reward', type: 'tuple', }, ]; /** * The Route struct object - use our defined RouteAbi */ const RouteStruct = exports.RouteAbi; /** * The Reward struct object - use our defined RewardAbi */ const RewardStruct = exports.RewardAbi; /** * The Intent struct object - use our defined IntentAbi */ const IntentStruct = exports.IntentAbi; /** * Encodes the route parameters into ABI-encoded bytes according to the contract structure. * This function ensures proper encoding of route data for protocol interactions. * * @param route - The route object following the RouteType structure defined by the contract * @returns Hex-encoded ABI-encoded representation of the route * * @example * // Encode a route for an intent * const encodedRoute = encodeRoute({ * fromChain: 1n, * toChain: 10n, * fromToken: '0x1234...', * toToken: '0xabcd...', * amount: 1000000n, * targetAddress: '0x9876...' * }); */ function encodeRoute(route) { return (0, viem_1.encodeAbiParameters)([{ type: 'tuple', components: RouteStruct }], [route]); } exports.encodeRoute = encodeRoute; /** * Decodes ABI-encoded route data back into a structured TypeScript RouteType object. * This function is the inverse of encodeRoute and extracts a readable route object * from its compact binary representation. * * @param route - Hex-encoded ABI representation of a route structure * @returns Decoded RouteType object with all route parameters in their proper types * * @example * // Decode an encoded route back to a route object * const route = decodeRoute('0x...'); * console.log(`Transfer from chain ${route.fromChain} to ${route.toChain}`); */ function decodeRoute(route) { return (0, viem_1.decodeAbiParameters)([{ type: 'tuple', components: RouteStruct }], route)[0]; } exports.decodeRoute = decodeRoute; /** * Encodes reward parameters into ABI-encoded bytes according to the contract structure. * This function creates a properly formatted binary representation of reward data * for use in protocol transactions and state verification. * * @param reward - The reward object following the RewardType structure defined by the contract * @returns Hex-encoded ABI-encoded representation of the reward * * @example * // Encode a reward specification for an intent * const encodedReward = encodeReward({ * rewardToken: '0x1234...', * rewardAmount: 1000000n, * deadline: 1735689600n, // Unix timestamp * recipient: '0x9876...' * }); */ function encodeReward(reward) { return (0, viem_1.encodeAbiParameters)([{ type: 'tuple', components: RewardStruct }], [reward]); } exports.encodeReward = encodeReward; /** * Decodes ABI-encoded reward data back into a structured TypeScript RewardType object. * This function is the inverse of encodeReward and processes binary reward data * into a developer-friendly object format with typed properties. * * @param reward - Hex-encoded ABI representation of a reward structure * @returns Decoded RewardType object with all reward parameters in their proper types * * @example * // Decode an encoded reward back to a reward object * const reward = decodeReward('0x...'); * console.log(`Reward of ${reward.rewardAmount} tokens available until ${new Date(Number(reward.deadline) * 1000)}`); */ function decodeReward(reward) { return (0, viem_1.decodeAbiParameters)([{ type: 'tuple', components: RewardStruct }], reward)[0]; } exports.decodeReward = decodeReward; /** * Encodes the complete intent structure (combining route and reward) into packed binary format. * This function creates the official on-chain representation of an intent as used by * the intent source contract, preserving the exact same encoding as the solidity implementation. * * @param intent - The intent object containing both route and reward structures * @returns Hex-encoded packed representation of the complete intent * * @example * // Encode a complete intent with route and reward * const encodedIntent = encodeIntent({ * route: { fromChain: 1n, toChain: 10n, ... }, * reward: { rewardToken: '0x1234...', rewardAmount: 1000000n, ... } * }); */ function encodeIntent(intent) { return (0, viem_1.encodeAbiParameters)([{ type: 'tuple', components: IntentStruct }], [intent]); } exports.encodeIntent = encodeIntent; /** * Decodes a complete intent from its packed binary representation back to a structured object. * This function is the inverse of encodeIntent and extracts the full intent data including * both route and reward components for client-side processing and validation. * * @param intent - Hex-encoded packed representation of a complete intent * @returns Decoded IntentType object with nested route and reward structures * * @example * // Decode an encoded intent back to an intent object * const intent = decodeIntent('0x...'); * console.log(`Intent: ${intent.route.fromChain} -> ${intent.route.toChain} with reward ${intent.reward.rewardAmount}`); */ function decodeIntent(intent) { return (0, viem_1.decodeAbiParameters)([{ type: 'tuple', components: IntentStruct }], intent)[0]; } exports.decodeIntent = decodeIntent; /** * Computes the keccak256 hash of an encoded route structure, matching the hashing * algorithm used on-chain. This hash uniquely identifies route parameters and * can be used for verification and intent matching. * * @param route - The route object to hash, following the RouteType structure * @returns Hex-encoded keccak256 hash of the encoded route * * @example * // Hash a route for verification * const routeHash = hashRoute({ * fromChain: 1n, * toChain: 10n, * // other route parameters * }); */ function hashRoute(route) { return (0, viem_1.keccak256)(encodeRoute(route)); } exports.hashRoute = hashRoute; /** * Computes the keccak256 hash of an encoded reward structure, matching the hashing * algorithm used on-chain. This hash uniquely identifies reward parameters and * can be used for verification and reward claiming. * * @param reward - The reward object to hash, following the RewardType structure * @returns Hex-encoded keccak256 hash of the encoded reward * * @example * // Hash a reward for verification * const rewardHash = hashReward({ * rewardToken: '0x1234...', * rewardAmount: 1000000n, * // other reward parameters * }); */ function hashReward(reward) { return (0, viem_1.keccak256)(encodeReward(reward)); } exports.hashReward = hashReward; /** * Computes all hashes for an intent, including the route hash, reward hash, and * the combined intent hash that uniquely identifies the entire intent. This function * precisely matches the on-chain hashing algorithms used by the Portal contract. * * The intent hash is derived from the route and reward hashes (not directly from their structures), * ensuring consistency with the on-chain implementation which uses the same approach. * * @param intent - The complete intent object containing both route and reward structures * @returns Object containing the routeHash, rewardHash, and the combined intentHash * * @example * // Generate all hashes for an intent * const hashes = hashIntent({ * route: { fromChain: 1n, toChain: 10n, }, * reward: { rewardToken: '0x1234...', rewardAmount: 1000000n, } * }); * console.log(`Intent hash: ${hashes.intentHash}`); */ function hashIntent(destination, route, reward) { const routeHash = hashRoute(route); const rewardHash = hashReward(reward); const intentHash = (0, viem_1.keccak256)((0, viem_1.encodePacked)(['uint64', 'bytes32', 'bytes32'], [destination, routeHash, rewardHash])); return { routeHash, rewardHash, intentHash, }; } exports.hashIntent = hashIntent;