UNPKG

@uniswap/v4-sdk

Version:

⚒️ An SDK for building applications on top of Uniswap V4

189 lines 6.98 kB
import { ethers } from 'ethers'; import { Actions, Subparser, URVersion, isAtLeastV2_1_1, V4_BASE_ACTIONS_ABI_DEFINITION, V4_SWAP_ACTIONS_V2_1_1, } from './v4Planner'; // Parses V4Router actions export class V4BaseActionsParser { static parseCalldata(calldata, urVersion = URVersion.V2_0) { const [actions, inputs] = ethers.utils.defaultAbiCoder.decode(['bytes', 'bytes[]'], calldata); const actionTypes = V4BaseActionsParser.getActions(actions); return { actions: actionTypes.map((actionType, i) => { // Use V2.1.1 ABI for swap actions if V2.1.1, otherwise use base ABI (V2.0) const abiDef = isAtLeastV2_1_1(urVersion) && actionType in V4_SWAP_ACTIONS_V2_1_1 ? V4_SWAP_ACTIONS_V2_1_1[actionType] : V4_BASE_ACTIONS_ABI_DEFINITION[actionType]; const rawParams = ethers.utils.defaultAbiCoder.decode(abiDef.map((command) => command.type), inputs[i]); const params = rawParams.map((param, j) => { switch (abiDef[j].subparser) { case Subparser.V4SwapExactInSingle: return { name: abiDef[j].name, value: parseV4ExactInSingle(param, urVersion), }; case Subparser.V4SwapExactIn: return { name: abiDef[j].name, value: parseV4ExactIn(param, urVersion), }; case Subparser.V4SwapExactOutSingle: return { name: abiDef[j].name, value: parseV4ExactOutSingle(param, urVersion), }; case Subparser.V4SwapExactOut: return { name: abiDef[j].name, value: parseV4ExactOut(param, urVersion), }; case Subparser.PoolKey: return { name: abiDef[j].name, value: parsePoolKey(param), }; default: return { name: abiDef[j].name, value: param, }; } }); return { actionName: Actions[actionType], actionType, params, }; }), }; } // parse command types from bytes string static getActions(actions) { const actionTypes = []; for (let i = 2; i < actions.length; i += 2) { const byte = actions.substring(i, i + 2); actionTypes.push(parseInt(byte, 16)); } return actionTypes; } } function parsePoolKey(data) { const [currency0, currency1, fee, tickSpacing, hooks] = data; return { currency0, currency1, fee: parseInt(fee), tickSpacing: parseInt(tickSpacing), hooks, }; } function parsePathKey(data) { const [intermediateCurrency, fee, tickSpacing, hooks, hookData] = data; return { intermediateCurrency, fee: parseInt(fee), tickSpacing: parseInt(tickSpacing), hooks, hookData, }; } function parseV4ExactInSingle(data, urVersion) { const [currency0, currency1, fee, tickSpacing, hooks] = data[0]; const poolKey = { currency0, currency1, fee, tickSpacing, hooks }; if (urVersion === URVersion.V2_0) { // V2.0: [poolKey, zeroForOne, amountIn, amountOutMinimum, hookData] const [, zeroForOne, amountIn, amountOutMinimum, hookData] = data; return { poolKey, zeroForOne, amountIn, amountOutMinimum, hookData, }; } else { // V2.1.1: [poolKey, zeroForOne, amountIn, amountOutMinimum, minHopPriceX36, hookData] const [, zeroForOne, amountIn, amountOutMinimum, minHopPriceX36, hookData] = data; return { poolKey, zeroForOne, amountIn, amountOutMinimum, minHopPriceX36, hookData, }; } } function parseV4ExactIn(data, urVersion) { const paths = data[1].map((pathKey) => parsePathKey(pathKey)); if (urVersion === URVersion.V2_0) { // V2.0: [currencyIn, path, amountIn, amountOutMinimum] const [currencyIn, , amountIn, amountOutMinimum] = data; return { currencyIn, path: paths, amountIn, amountOutMinimum, }; } else { // V2.1.1: [currencyIn, path, minHopPriceX36, amountIn, amountOutMinimum] const [currencyIn, , minHopPriceX36, amountIn, amountOutMinimum] = data; return { currencyIn, path: paths, minHopPriceX36, amountIn, amountOutMinimum, }; } } function parseV4ExactOutSingle(data, urVersion) { const [currency0, currency1, fee, tickSpacing, hooks] = data[0]; const poolKey = { currency0, currency1, fee, tickSpacing, hooks }; if (urVersion === URVersion.V2_0) { // V2.0: [poolKey, zeroForOne, amountOut, amountInMaximum, hookData] const [, zeroForOne, amountOut, amountInMaximum, hookData] = data; return { poolKey, zeroForOne, amountOut, amountInMaximum, hookData, }; } else { // V2.1.1: [poolKey, zeroForOne, amountOut, amountInMaximum, minHopPriceX36, hookData] const [, zeroForOne, amountOut, amountInMaximum, minHopPriceX36, hookData] = data; return { poolKey, zeroForOne, amountOut, amountInMaximum, minHopPriceX36, hookData, }; } } function parseV4ExactOut(data, urVersion) { const paths = data[1].map((pathKey) => parsePathKey(pathKey)); if (urVersion === URVersion.V2_0) { // V2.0: [currencyOut, path, amountOut, amountInMaximum] const [currencyOut, , amountOut, amountInMaximum] = data; return { currencyOut, path: paths, amountOut, amountInMaximum, }; } else { // V2.1.1: [currencyOut, path, minHopPriceX36, amountOut, amountInMaximum] const [currencyOut, , minHopPriceX36, amountOut, amountInMaximum] = data; return { currencyOut, path: paths, minHopPriceX36, amountOut, amountInMaximum, }; } } //# sourceMappingURL=v4BaseActionsParser.js.map