diff --git a/assets/logos/hyperliquid.svg b/assets/logos/hyperliquid.svg
new file mode 100644
index 0000000..0b7b721
--- /dev/null
+++ b/assets/logos/hyperliquid.svg
@@ -0,0 +1,3 @@
+
diff --git a/lib/abis/aerodrome_v3_pool.abi.json b/lib/abis/aerodrome_v3_pool.abi.json
new file mode 100644
index 0000000..731bdaf
--- /dev/null
+++ b/lib/abis/aerodrome_v3_pool.abi.json
@@ -0,0 +1,1309 @@
+[
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "indexed": true,
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "amount",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "name": "Burn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "indexed": true,
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "amount0",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "amount1",
+ "type": "uint128"
+ }
+ ],
+ "name": "Collect",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "amount0",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "amount1",
+ "type": "uint128"
+ }
+ ],
+ "name": "CollectFees",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "paid0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "paid1",
+ "type": "uint256"
+ }
+ ],
+ "name": "Flash",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint16",
+ "name": "observationCardinalityNextOld",
+ "type": "uint16"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint16",
+ "name": "observationCardinalityNextNew",
+ "type": "uint16"
+ }
+ ],
+ "name": "IncreaseObservationCardinalityNext",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint160",
+ "name": "sqrtPriceX96",
+ "type": "uint160"
+ },
+ {
+ "indexed": false,
+ "internalType": "int24",
+ "name": "tick",
+ "type": "int24"
+ }
+ ],
+ "name": "Initialize",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "indexed": true,
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "amount",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "name": "Mint",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint8",
+ "name": "feeProtocol0Old",
+ "type": "uint8"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint8",
+ "name": "feeProtocol1Old",
+ "type": "uint8"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint8",
+ "name": "feeProtocol0New",
+ "type": "uint8"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint8",
+ "name": "feeProtocol1New",
+ "type": "uint8"
+ }
+ ],
+ "name": "SetFeeProtocol",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "int256",
+ "name": "amount0",
+ "type": "int256"
+ },
+ {
+ "indexed": false,
+ "internalType": "int256",
+ "name": "amount1",
+ "type": "int256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint160",
+ "name": "sqrtPriceX96",
+ "type": "uint160"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "int24",
+ "name": "tick",
+ "type": "int24"
+ }
+ ],
+ "name": "Swap",
+ "type": "event"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount",
+ "type": "uint128"
+ },
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ }
+ ],
+ "name": "burn",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount",
+ "type": "uint128"
+ }
+ ],
+ "name": "burn",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount0Requested",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount1Requested",
+ "type": "uint128"
+ },
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ }
+ ],
+ "name": "collect",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "amount0",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount1",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount0Requested",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount1Requested",
+ "type": "uint128"
+ }
+ ],
+ "name": "collect",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "amount0",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount1",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "collectFees",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "amount0",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount1",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "factory",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "factoryRegistry",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "fee",
+ "outputs": [
+ {
+ "internalType": "uint24",
+ "name": "",
+ "type": "uint24"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "feeGrowthGlobal0X128",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "feeGrowthGlobal1X128",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "flash",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "gauge",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "gaugeFees",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "token0",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "token1",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_rewardGrowthGlobalX128",
+ "type": "uint256"
+ }
+ ],
+ "name": "getRewardGrowthInside",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "rewardGrowthInside",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint16",
+ "name": "observationCardinalityNext",
+ "type": "uint16"
+ }
+ ],
+ "name": "increaseObservationCardinalityNext",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_factory",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_token0",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_token1",
+ "type": "address"
+ },
+ {
+ "internalType": "int24",
+ "name": "_tickSpacing",
+ "type": "int24"
+ },
+ {
+ "internalType": "address",
+ "name": "_factoryRegistry",
+ "type": "address"
+ },
+ {
+ "internalType": "uint160",
+ "name": "_sqrtPriceX96",
+ "type": "uint160"
+ }
+ ],
+ "name": "initialize",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "lastUpdated",
+ "outputs": [
+ {
+ "internalType": "uint32",
+ "name": "",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "liquidity",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "maxLiquidityPerTick",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount",
+ "type": "uint128"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "mint",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "nft",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "observations",
+ "outputs": [
+ {
+ "internalType": "uint32",
+ "name": "blockTimestamp",
+ "type": "uint32"
+ },
+ {
+ "internalType": "int56",
+ "name": "tickCumulative",
+ "type": "int56"
+ },
+ {
+ "internalType": "uint160",
+ "name": "secondsPerLiquidityCumulativeX128",
+ "type": "uint160"
+ },
+ {
+ "internalType": "bool",
+ "name": "initialized",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32[]",
+ "name": "secondsAgos",
+ "type": "uint32[]"
+ }
+ ],
+ "name": "observe",
+ "outputs": [
+ {
+ "internalType": "int56[]",
+ "name": "tickCumulatives",
+ "type": "int56[]"
+ },
+ {
+ "internalType": "uint160[]",
+ "name": "secondsPerLiquidityCumulativeX128s",
+ "type": "uint160[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "periodFinish",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "name": "positions",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint256",
+ "name": "feeGrowthInside0LastX128",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "feeGrowthInside1LastX128",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint128",
+ "name": "tokensOwed0",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "tokensOwed1",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "rewardGrowthGlobalX128",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "rewardRate",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "rewardReserve",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "rollover",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_gauge",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_nft",
+ "type": "address"
+ }
+ ],
+ "name": "setGaugeAndPositionManager",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "slot0",
+ "outputs": [
+ {
+ "internalType": "uint160",
+ "name": "sqrtPriceX96",
+ "type": "uint160"
+ },
+ {
+ "internalType": "int24",
+ "name": "tick",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint16",
+ "name": "observationIndex",
+ "type": "uint16"
+ },
+ {
+ "internalType": "uint16",
+ "name": "observationCardinality",
+ "type": "uint16"
+ },
+ {
+ "internalType": "uint16",
+ "name": "observationCardinalityNext",
+ "type": "uint16"
+ },
+ {
+ "internalType": "bool",
+ "name": "unlocked",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ }
+ ],
+ "name": "snapshotCumulativesInside",
+ "outputs": [
+ {
+ "internalType": "int56",
+ "name": "tickCumulativeInside",
+ "type": "int56"
+ },
+ {
+ "internalType": "uint160",
+ "name": "secondsPerLiquidityInsideX128",
+ "type": "uint160"
+ },
+ {
+ "internalType": "uint32",
+ "name": "secondsInside",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "int128",
+ "name": "stakedLiquidityDelta",
+ "type": "int128"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "internalType": "bool",
+ "name": "positionUpdate",
+ "type": "bool"
+ }
+ ],
+ "name": "stake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "stakedLiquidity",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "bool",
+ "name": "zeroForOne",
+ "type": "bool"
+ },
+ {
+ "internalType": "int256",
+ "name": "amountSpecified",
+ "type": "int256"
+ },
+ {
+ "internalType": "uint160",
+ "name": "sqrtPriceLimitX96",
+ "type": "uint160"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "swap",
+ "outputs": [
+ {
+ "internalType": "int256",
+ "name": "amount0",
+ "type": "int256"
+ },
+ {
+ "internalType": "int256",
+ "name": "amount1",
+ "type": "int256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "_rewardRate",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_rewardReserve",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_periodFinish",
+ "type": "uint256"
+ }
+ ],
+ "name": "syncReward",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "int16",
+ "name": "",
+ "type": "int16"
+ }
+ ],
+ "name": "tickBitmap",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "tickSpacing",
+ "outputs": [
+ {
+ "internalType": "int24",
+ "name": "",
+ "type": "int24"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "int24",
+ "name": "",
+ "type": "int24"
+ }
+ ],
+ "name": "ticks",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "liquidityGross",
+ "type": "uint128"
+ },
+ {
+ "internalType": "int128",
+ "name": "liquidityNet",
+ "type": "int128"
+ },
+ {
+ "internalType": "int128",
+ "name": "stakedLiquidityNet",
+ "type": "int128"
+ },
+ {
+ "internalType": "uint256",
+ "name": "feeGrowthOutside0X128",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "feeGrowthOutside1X128",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "rewardGrowthOutsideX128",
+ "type": "uint256"
+ },
+ {
+ "internalType": "int56",
+ "name": "tickCumulativeOutside",
+ "type": "int56"
+ },
+ {
+ "internalType": "uint160",
+ "name": "secondsPerLiquidityOutsideX128",
+ "type": "uint160"
+ },
+ {
+ "internalType": "uint32",
+ "name": "secondsOutside",
+ "type": "uint32"
+ },
+ {
+ "internalType": "bool",
+ "name": "initialized",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "token0",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "token1",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "unstakedFee",
+ "outputs": [
+ {
+ "internalType": "uint24",
+ "name": "",
+ "type": "uint24"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "updateRewardsGrowthGlobal",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+]
\ No newline at end of file
diff --git a/lib/abis/aerodrome_v3_position_manager.abi.json b/lib/abis/aerodrome_v3_position_manager.abi.json
new file mode 100644
index 0000000..ca21600
--- /dev/null
+++ b/lib/abis/aerodrome_v3_position_manager.abi.json
@@ -0,0 +1,1312 @@
+[
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_factory",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_WETH9",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_tokenDescriptor",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "name",
+ "type": "string"
+ },
+ {
+ "internalType": "string",
+ "name": "symbol",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "approved",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "operator",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "name": "ApprovalForAll",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "_fromTokenId",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "_toTokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "BatchMetadataUpdate",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "name": "Collect",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "name": "DecreaseLiquidity",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "name": "IncreaseLiquidity",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "_tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "MetadataUpdate",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "tokenDescriptor",
+ "type": "address"
+ }
+ ],
+ "name": "TokenDescriptorChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ }
+ ],
+ "name": "TransferOwnership",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "DOMAIN_SEPARATOR",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "PERMIT_TYPEHASH",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "WETH9",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "approve",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "baseURI",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "pure",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "burn",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount0Max",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount1Max",
+ "type": "uint128"
+ }
+ ],
+ "internalType": "struct INonfungiblePositionManager.CollectParams",
+ "name": "params",
+ "type": "tuple"
+ }
+ ],
+ "name": "collect",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0Min",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1Min",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct INonfungiblePositionManager.DecreaseLiquidityParams",
+ "name": "params",
+ "type": "tuple"
+ }
+ ],
+ "name": "decreaseLiquidity",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "factory",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "getApproved",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0Desired",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1Desired",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0Min",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1Min",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct INonfungiblePositionManager.IncreaseLiquidityParams",
+ "name": "params",
+ "type": "tuple"
+ }
+ ],
+ "name": "increaseLiquidity",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address"
+ }
+ ],
+ "name": "isApprovedForAll",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "token0",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "token1",
+ "type": "address"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickSpacing",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0Desired",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1Desired",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0Min",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1Min",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint160",
+ "name": "sqrtPriceX96",
+ "type": "uint160"
+ }
+ ],
+ "internalType": "struct INonfungiblePositionManager.MintParams",
+ "name": "params",
+ "type": "tuple"
+ }
+ ],
+ "name": "mint",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes[]",
+ "name": "data",
+ "type": "bytes[]"
+ }
+ ],
+ "name": "multicall",
+ "outputs": [
+ {
+ "internalType": "bytes[]",
+ "name": "results",
+ "type": "bytes[]"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "name",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "ownerOf",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "permit",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "positions",
+ "outputs": [
+ {
+ "internalType": "uint96",
+ "name": "nonce",
+ "type": "uint96"
+ },
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "token0",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "token1",
+ "type": "address"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickSpacing",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint256",
+ "name": "feeGrowthInside0LastX128",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "feeGrowthInside1LastX128",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint128",
+ "name": "tokensOwed0",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "tokensOwed1",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "refundETH",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "safeTransferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "_data",
+ "type": "bytes"
+ }
+ ],
+ "name": "safeTransferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "selfPermit",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "expiry",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "selfPermitAllowed",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "expiry",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "selfPermitAllowedIfNecessary",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "selfPermitIfNecessary",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address"
+ },
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "name": "setApprovalForAll",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_owner",
+ "type": "address"
+ }
+ ],
+ "name": "setOwner",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_tokenDescriptor",
+ "type": "address"
+ }
+ ],
+ "name": "setTokenDescriptor",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes4",
+ "name": "interfaceId",
+ "type": "bytes4"
+ }
+ ],
+ "name": "supportsInterface",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amountMinimum",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ }
+ ],
+ "name": "sweepToken",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "symbol",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "index",
+ "type": "uint256"
+ }
+ ],
+ "name": "tokenByIndex",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "tokenDescriptor",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "index",
+ "type": "uint256"
+ }
+ ],
+ "name": "tokenOfOwnerByIndex",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "tokenURI",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount0Owed",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1Owed",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "uniswapV3MintCallback",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "amountMinimum",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ }
+ ],
+ "name": "unwrapWETH9",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+]
\ No newline at end of file
diff --git a/lib/abis/algebra/v1.2.1/pool.abi.json b/lib/abis/algebra/v1.2.1/pool.abi.json
new file mode 100644
index 0000000..db1e74c
--- /dev/null
+++ b/lib/abis/algebra/v1.2.1/pool.abi.json
@@ -0,0 +1,1381 @@
+[
+ {
+ "inputs": [],
+ "name": "alreadyInitialized",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "arithmeticError",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "bottomTickLowerThanMIN",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "dynamicFeeActive",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "dynamicFeeDisabled",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "flashInsufficientPaid0",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "flashInsufficientPaid1",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "incorrectPluginFee",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "insufficientInputAmount",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "invalidAmountRequired",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes4",
+ "name": "expectedSelector",
+ "type": "bytes4"
+ }
+ ],
+ "name": "invalidHookResponse",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "invalidLimitSqrtPrice",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "invalidNewCommunityFee",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "invalidNewTickSpacing",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "liquidityAdd",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "liquidityOverflow",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "liquiditySub",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "locked",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "notAllowed",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "notInitialized",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "pluginIsNotConnected",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "priceOutOfRange",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "tickInvalidLinks",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "tickIsNotInitialized",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "tickIsNotSpaced",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "tickOutOfRange",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "topTickAboveMAX",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "topTickLowerOrEqBottomTick",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "transferFailed",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "zeroAmountRequired",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "zeroLiquidityActual",
+ "type": "error"
+ },
+ {
+ "inputs": [],
+ "name": "zeroLiquidityDesired",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "int24",
+ "name": "bottomTick",
+ "type": "int24"
+ },
+ {
+ "indexed": true,
+ "internalType": "int24",
+ "name": "topTick",
+ "type": "int24"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "liquidityAmount",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint24",
+ "name": "pluginFee",
+ "type": "uint24"
+ }
+ ],
+ "name": "Burn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "int24",
+ "name": "bottomTick",
+ "type": "int24"
+ },
+ {
+ "indexed": true,
+ "internalType": "int24",
+ "name": "topTick",
+ "type": "int24"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "amount0",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "amount1",
+ "type": "uint128"
+ }
+ ],
+ "name": "Collect",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint16",
+ "name": "communityFeeNew",
+ "type": "uint16"
+ }
+ ],
+ "name": "CommunityFee",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "newCommunityVault",
+ "type": "address"
+ }
+ ],
+ "name": "CommunityVault",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "name": "ExcessTokens",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint16",
+ "name": "fee",
+ "type": "uint16"
+ }
+ ],
+ "name": "Fee",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "paid0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "paid1",
+ "type": "uint256"
+ }
+ ],
+ "name": "Flash",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint160",
+ "name": "price",
+ "type": "uint160"
+ },
+ {
+ "indexed": false,
+ "internalType": "int24",
+ "name": "tick",
+ "type": "int24"
+ }
+ ],
+ "name": "Initialize",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "int24",
+ "name": "bottomTick",
+ "type": "int24"
+ },
+ {
+ "indexed": true,
+ "internalType": "int24",
+ "name": "topTick",
+ "type": "int24"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "liquidityAmount",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "name": "Mint",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "newPluginAddress",
+ "type": "address"
+ }
+ ],
+ "name": "Plugin",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint8",
+ "name": "newPluginConfig",
+ "type": "uint8"
+ }
+ ],
+ "name": "PluginConfig",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "name": "Skim",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "int256",
+ "name": "amount0",
+ "type": "int256"
+ },
+ {
+ "indexed": false,
+ "internalType": "int256",
+ "name": "amount1",
+ "type": "int256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint160",
+ "name": "price",
+ "type": "uint160"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "int24",
+ "name": "tick",
+ "type": "int24"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint24",
+ "name": "overrideFee",
+ "type": "uint24"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint24",
+ "name": "pluginFee",
+ "type": "uint24"
+ }
+ ],
+ "name": "Swap",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "int24",
+ "name": "newTickSpacing",
+ "type": "int24"
+ }
+ ],
+ "name": "TickSpacing",
+ "type": "event"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "int24",
+ "name": "bottomTick",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "topTick",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount",
+ "type": "uint128"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "burn",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "int24",
+ "name": "bottomTick",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "topTick",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount0Requested",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount1Requested",
+ "type": "uint128"
+ }
+ ],
+ "name": "collect",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "amount0",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount1",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "communityVault",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "factory",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "fee",
+ "outputs": [
+ {
+ "internalType": "uint16",
+ "name": "currentFee",
+ "type": "uint16"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "flash",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getCommunityFeePending",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getPluginFeePending",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "getReserves",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "globalState",
+ "outputs": [
+ {
+ "internalType": "uint160",
+ "name": "price",
+ "type": "uint160"
+ },
+ {
+ "internalType": "int24",
+ "name": "tick",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint16",
+ "name": "lastFee",
+ "type": "uint16"
+ },
+ {
+ "internalType": "uint8",
+ "name": "pluginConfig",
+ "type": "uint8"
+ },
+ {
+ "internalType": "uint16",
+ "name": "communityFee",
+ "type": "uint16"
+ },
+ {
+ "internalType": "bool",
+ "name": "unlocked",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint160",
+ "name": "initialPrice",
+ "type": "uint160"
+ }
+ ],
+ "name": "initialize",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "isUnlocked",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "unlocked",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "lastFeeTransferTimestamp",
+ "outputs": [
+ {
+ "internalType": "uint32",
+ "name": "",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "liquidity",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "maxLiquidityPerTick",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "leftoversRecipient",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "int24",
+ "name": "bottomTick",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "topTick",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint128",
+ "name": "liquidityDesired",
+ "type": "uint128"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "mint",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint128",
+ "name": "liquidityActual",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "nextTickGlobal",
+ "outputs": [
+ {
+ "internalType": "int24",
+ "name": "",
+ "type": "int24"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "plugin",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "name": "positions",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "liquidity",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "innerFeeGrowth0Token",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "innerFeeGrowth1Token",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint128",
+ "name": "fees0",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "fees1",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "prevTickGlobal",
+ "outputs": [
+ {
+ "internalType": "int24",
+ "name": "",
+ "type": "int24"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "safelyGetStateOfAMM",
+ "outputs": [
+ {
+ "internalType": "uint160",
+ "name": "sqrtPrice",
+ "type": "uint160"
+ },
+ {
+ "internalType": "int24",
+ "name": "tick",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint16",
+ "name": "lastFee",
+ "type": "uint16"
+ },
+ {
+ "internalType": "uint8",
+ "name": "pluginConfig",
+ "type": "uint8"
+ },
+ {
+ "internalType": "uint128",
+ "name": "activeLiquidity",
+ "type": "uint128"
+ },
+ {
+ "internalType": "int24",
+ "name": "nextTick",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "previousTick",
+ "type": "int24"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint16",
+ "name": "newCommunityFee",
+ "type": "uint16"
+ }
+ ],
+ "name": "setCommunityFee",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newCommunityVault",
+ "type": "address"
+ }
+ ],
+ "name": "setCommunityVault",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint16",
+ "name": "newFee",
+ "type": "uint16"
+ }
+ ],
+ "name": "setFee",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newPluginAddress",
+ "type": "address"
+ }
+ ],
+ "name": "setPlugin",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint8",
+ "name": "newConfig",
+ "type": "uint8"
+ }
+ ],
+ "name": "setPluginConfig",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "int24",
+ "name": "newTickSpacing",
+ "type": "int24"
+ }
+ ],
+ "name": "setTickSpacing",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "skim",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "bool",
+ "name": "zeroToOne",
+ "type": "bool"
+ },
+ {
+ "internalType": "int256",
+ "name": "amountRequired",
+ "type": "int256"
+ },
+ {
+ "internalType": "uint160",
+ "name": "limitSqrtPrice",
+ "type": "uint160"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "swap",
+ "outputs": [
+ {
+ "internalType": "int256",
+ "name": "amount0",
+ "type": "int256"
+ },
+ {
+ "internalType": "int256",
+ "name": "amount1",
+ "type": "int256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "leftoversRecipient",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "bool",
+ "name": "zeroToOne",
+ "type": "bool"
+ },
+ {
+ "internalType": "int256",
+ "name": "amountToSell",
+ "type": "int256"
+ },
+ {
+ "internalType": "uint160",
+ "name": "limitSqrtPrice",
+ "type": "uint160"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "swapWithPaymentInAdvance",
+ "outputs": [
+ {
+ "internalType": "int256",
+ "name": "amount0",
+ "type": "int256"
+ },
+ {
+ "internalType": "int256",
+ "name": "amount1",
+ "type": "int256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "sync",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "tickSpacing",
+ "outputs": [
+ {
+ "internalType": "int24",
+ "name": "",
+ "type": "int24"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "int16",
+ "name": "",
+ "type": "int16"
+ }
+ ],
+ "name": "tickTable",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "tickTreeRoot",
+ "outputs": [
+ {
+ "internalType": "uint32",
+ "name": "",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "int16",
+ "name": "",
+ "type": "int16"
+ }
+ ],
+ "name": "tickTreeSecondLayer",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "int24",
+ "name": "",
+ "type": "int24"
+ }
+ ],
+ "name": "ticks",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "liquidityTotal",
+ "type": "uint256"
+ },
+ {
+ "internalType": "int128",
+ "name": "liquidityDelta",
+ "type": "int128"
+ },
+ {
+ "internalType": "int24",
+ "name": "prevTick",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "nextTick",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint256",
+ "name": "outerFeeGrowth0Token",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "outerFeeGrowth1Token",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "token0",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "token1",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "totalFeeGrowth0Token",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "totalFeeGrowth1Token",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ }
+]
\ No newline at end of file
diff --git a/lib/abis/algebra/v1.2.1/position_manager.abi.json b/lib/abis/algebra/v1.2.1/position_manager.abi.json
new file mode 100644
index 0000000..b22ffc5
--- /dev/null
+++ b/lib/abis/algebra/v1.2.1/position_manager.abi.json
@@ -0,0 +1,1403 @@
+[
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_factory",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_WNativeToken",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_tokenDescriptor_",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_poolDeployer",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [],
+ "name": "tickOutOfRange",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "approved",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "Approval",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "operator",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "name": "ApprovalForAll",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "name": "Collect",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "name": "DecreaseLiquidity",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "FarmingFailed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "liquidityDesired",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "actualLiquidity",
+ "type": "uint128"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "pool",
+ "type": "address"
+ }
+ ],
+ "name": "IncreaseLiquidity",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "Transfer",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "DOMAIN_SEPARATOR",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "NONFUNGIBLE_POSITION_MANAGER_ADMINISTRATOR_ROLE",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "PERMIT_TYPEHASH",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "WNativeToken",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount0Owed",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1Owed",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "algebraMintCallback",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "approve",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "approve",
+ "type": "bool"
+ },
+ {
+ "internalType": "address",
+ "name": "farmingAddress",
+ "type": "address"
+ }
+ ],
+ "name": "approveForFarming",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "burn",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount0Max",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "amount1Max",
+ "type": "uint128"
+ }
+ ],
+ "internalType": "struct INonfungiblePositionManager.CollectParams",
+ "name": "params",
+ "type": "tuple"
+ }
+ ],
+ "name": "collect",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token0",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "token1",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "deployer",
+ "type": "address"
+ },
+ {
+ "internalType": "uint160",
+ "name": "sqrtPriceX96",
+ "type": "uint160"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "createAndInitializePoolIfNecessary",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "pool",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0Min",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1Min",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct INonfungiblePositionManager.DecreaseLiquidityParams",
+ "name": "params",
+ "type": "tuple"
+ }
+ ],
+ "name": "decreaseLiquidity",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "factory",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "farmingApprovals",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "farmingCenterAddress",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "farmingCenter",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "getApproved",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0Desired",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1Desired",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0Min",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1Min",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct INonfungiblePositionManager.IncreaseLiquidityParams",
+ "name": "params",
+ "type": "tuple"
+ }
+ ],
+ "name": "increaseLiquidity",
+ "outputs": [
+ {
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address"
+ }
+ ],
+ "name": "isApprovedForAll",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "isApprovedOrOwner",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "token0",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "token1",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "deployer",
+ "type": "address"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0Desired",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1Desired",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0Min",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1Min",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct INonfungiblePositionManager.MintParams",
+ "name": "params",
+ "type": "tuple"
+ }
+ ],
+ "name": "mint",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount0",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount1",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes[]",
+ "name": "data",
+ "type": "bytes[]"
+ }
+ ],
+ "name": "multicall",
+ "outputs": [
+ {
+ "internalType": "bytes[]",
+ "name": "results",
+ "type": "bytes[]"
+ }
+ ],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "name",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "ownerOf",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "spender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "permit",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "poolDeployer",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "positions",
+ "outputs": [
+ {
+ "internalType": "uint88",
+ "name": "nonce",
+ "type": "uint88"
+ },
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "token0",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "token1",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "deployer",
+ "type": "address"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickLower",
+ "type": "int24"
+ },
+ {
+ "internalType": "int24",
+ "name": "tickUpper",
+ "type": "int24"
+ },
+ {
+ "internalType": "uint128",
+ "name": "liquidity",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint256",
+ "name": "feeGrowthInside0LastX128",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "feeGrowthInside1LastX128",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint128",
+ "name": "tokensOwed0",
+ "type": "uint128"
+ },
+ {
+ "internalType": "uint128",
+ "name": "tokensOwed1",
+ "type": "uint128"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "refundNativeToken",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "safeTransferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "data",
+ "type": "bytes"
+ }
+ ],
+ "name": "safeTransferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "selfPermit",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "expiry",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "selfPermitAllowed",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "expiry",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "selfPermitAllowedIfNecessary",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint8",
+ "name": "v",
+ "type": "uint8"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "r",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "s",
+ "type": "bytes32"
+ }
+ ],
+ "name": "selfPermitIfNecessary",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address"
+ },
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool"
+ }
+ ],
+ "name": "setApprovalForAll",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newFarmingCenter",
+ "type": "address"
+ }
+ ],
+ "name": "setFarmingCenter",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes4",
+ "name": "interfaceId",
+ "type": "bytes4"
+ }
+ ],
+ "name": "supportsInterface",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "token",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amountMinimum",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ }
+ ],
+ "name": "sweepToken",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "toActive",
+ "type": "bool"
+ }
+ ],
+ "name": "switchFarmingStatus",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "symbol",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "index",
+ "type": "uint256"
+ }
+ ],
+ "name": "tokenByIndex",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "tokenFarmedIn",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "farmingCenterAddress",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "index",
+ "type": "uint256"
+ }
+ ],
+ "name": "tokenOfOwnerByIndex",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "tokenURI",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "transferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "amountMinimum",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
+ }
+ ],
+ "name": "unwrapWNativeToken",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+]
\ No newline at end of file
diff --git a/lib/abis/pancake_swap_infinity_cl_pool_manager.abi.json b/lib/abis/pancake_swap_infinity_cl_pool_manager.abi.json
index 1117a3b..24da904 100644
--- a/lib/abis/pancake_swap_infinity_cl_pool_manager.abi.json
+++ b/lib/abis/pancake_swap_infinity_cl_pool_manager.abi.json
@@ -32,5 +32,49 @@
],
"stateMutability": "view",
"type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "PoolId",
+ "name": "id",
+ "type": "bytes32"
+ }
+ ],
+ "name": "poolIdToPoolKey",
+ "outputs": [
+ {
+ "internalType": "Currency",
+ "name": "currency0",
+ "type": "address"
+ },
+ {
+ "internalType": "Currency",
+ "name": "currency1",
+ "type": "address"
+ },
+ {
+ "internalType": "contract IHooks",
+ "name": "hooks",
+ "type": "address"
+ },
+ {
+ "internalType": "contract IPoolManager",
+ "name": "poolManager",
+ "type": "address"
+ },
+ {
+ "internalType": "uint24",
+ "name": "fee",
+ "type": "uint24"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "parameters",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
}
]
\ No newline at end of file
diff --git a/lib/abis/pancake_swap_infinity_cl_position_manager.abi.json b/lib/abis/pancake_swap_infinity_cl_position_manager.abi.json
new file mode 100644
index 0000000..dbff6ad
--- /dev/null
+++ b/lib/abis/pancake_swap_infinity_cl_position_manager.abi.json
@@ -0,0 +1,20 @@
+[
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "payload",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "deadline",
+ "type": "uint256"
+ }
+ ],
+ "name": "modifyLiquidities",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ }
+]
\ No newline at end of file
diff --git a/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit.dart b/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit.dart
index 6836217..1c96778 100644
--- a/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit.dart
+++ b/lib/app/create/deposit/widgets/preview_deposit_modal/preview_deposit_modal_cubit.dart
@@ -35,15 +35,15 @@ class PreviewDepositModalCubit extends Cubit with V3Po
required UniswapPermit2 permit2,
required GlobalKey navigatorKey,
required ZupAnalytics zupAnalytics,
- }) : _yield = currentYield,
- _poolRepository = poolService,
- _erc20 = erc20,
- _wallet = wallet,
- _latestPoolTick = initialPoolTick,
- _navigatorKey = navigatorKey,
- _zupAnalytics = zupAnalytics,
- _permit2 = permit2,
- super(const PreviewDepositModalState.loading());
+ }) : _yield = currentYield,
+ _poolRepository = poolService,
+ _erc20 = erc20,
+ _wallet = wallet,
+ _latestPoolTick = initialPoolTick,
+ _navigatorKey = navigatorKey,
+ _zupAnalytics = zupAnalytics,
+ _permit2 = permit2,
+ super(const PreviewDepositModalState.loading());
final PoolService _poolRepository;
final Erc20 _erc20;
@@ -76,12 +76,7 @@ class PreviewDepositModalCubit extends Cubit with V3Po
await _getTokensAllowance();
- emit(
- PreviewDepositModalState.initial(
- token0Allowance: _token0Allowance,
- token1Allowance: _token1Allowance,
- ),
- );
+ emit(PreviewDepositModalState.initial(token0Allowance: _token0Allowance, token1Allowance: _token1Allowance));
}
Future approveToken(TokenDto token, BigInt value) async {
@@ -92,10 +87,7 @@ class PreviewDepositModalCubit extends Cubit with V3Po
await _maybeSwitchNetwork();
- final contract = _erc20.fromSigner(
- contractAddress: tokenAddressInNetwork,
- signer: _wallet.signer!,
- );
+ final contract = _erc20.fromSigner(contractAddress: tokenAddressInNetwork, signer: _wallet.signer!);
final tx = await contract.approve(spender: spender, value: value);
@@ -131,10 +123,7 @@ class PreviewDepositModalCubit extends Cubit with V3Po
if (tokenAddressInNetwork == EthereumConstants.zeroAddress) return;
- final permit2Contract = _permit2.fromSigner(
- contractAddress: _yield.permit2!,
- signer: _wallet.signer!,
- );
+ final permit2Contract = _permit2.fromSigner(contractAddress: _yield.permit2!, signer: _wallet.signer!);
final permit2CurrentAllowance = await permit2Contract.allowance(
await _wallet.signer!.address,
@@ -183,10 +172,7 @@ class PreviewDepositModalCubit extends Cubit with V3Po
);
}
- return tickToClosestValidTick(
- tick: convertPriceToTickLower(),
- tickSpacing: _yield.tickSpacing,
- );
+ return tickToClosestValidTick(tick: convertPriceToTickLower(), tickSpacing: _yield.tickSpacing);
}
BigInt tickUpper() {
@@ -202,10 +188,7 @@ class PreviewDepositModalCubit extends Cubit with V3Po
);
}
- return tickToClosestValidTick(
- tick: convertPriceToTickUpper(),
- tickSpacing: _yield.tickSpacing,
- );
+ return tickToClosestValidTick(tick: convertPriceToTickUpper(), tickSpacing: _yield.tickSpacing);
}
final amount0Desired = token0Amount;
@@ -268,10 +251,7 @@ class PreviewDepositModalCubit extends Cubit with V3Po
if (e is UserRejectedAction) {
return emit(
- PreviewDepositModalState.initial(
- token0Allowance: _token0Allowance,
- token1Allowance: _token1Allowance,
- ),
+ PreviewDepositModalState.initial(token0Allowance: _token0Allowance, token1Allowance: _token1Allowance),
);
}
@@ -301,10 +281,7 @@ class PreviewDepositModalCubit extends Cubit with V3Po
rpcUrl: _yield.network.rpcUrl,
);
- _token0Allowance = await token0contract.allowance(
- owner: owner,
- spender: spender,
- );
+ _token0Allowance = await token0contract.allowance(owner: owner, spender: spender);
}
if (!_yield.isToken1Native) {
@@ -313,10 +290,7 @@ class PreviewDepositModalCubit extends Cubit with V3Po
rpcUrl: _yield.network.rpcUrl,
);
- _token1Allowance = await token1contract.allowance(
- owner: owner,
- spender: spender,
- );
+ _token1Allowance = await token1contract.allowance(owner: owner, spender: spender);
}
} catch (e) {
if (canThrow) rethrow;
@@ -339,14 +313,13 @@ class PreviewDepositModalCubit extends Cubit with V3Po
final stateAsWaitingTransaction = state as _WaitingTransaction;
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
- ScaffoldMessenger.of(context).showSnackBar(() {
- return switch (stateAsWaitingTransaction.type) {
- WaitingTransactionType.deposit => ZupSnackBar(
+ ScaffoldMessenger.of(context).showSnackBar(
+ () {
+ return switch (stateAsWaitingTransaction.type) {
+ WaitingTransactionType.deposit => ZupSnackBar(
context,
- message: "${S.of(context).previewDepositModalCubitDepositingSnackBarMessage(
- token0Symbol: _yield.token0.symbol,
- token1Symbol: _yield.token1.symbol,
- )} ",
+ message:
+ "${S.of(context).previewDepositModalCubitDepositingSnackBarMessage(token0Symbol: _yield.token0.symbol, token1Symbol: _yield.token1.symbol)} ",
customIcon: const ZupCircularLoadingIndicator(size: 20),
type: ZupSnackBarType.info,
maxWidth: 500,
@@ -356,20 +329,21 @@ class PreviewDepositModalCubit extends Cubit with V3Po
onButtonTap: () => _yield.network.openTx(stateAsWaitingTransaction.txId),
),
),
- WaitingTransactionType.approve => ZupSnackBar(
+ WaitingTransactionType.approve => ZupSnackBar(
context,
message: "${S.of(context).previewDepositModalCubitApprovingSnackBarMessage} ",
type: ZupSnackBarType.info,
maxWidth: 400,
helperButton: (
title: S.of(context).previewDepositModalWaitingTransactionSnackBarHelperButtonTitle,
- onButtonTap: () => _yield.network.openTx(stateAsWaitingTransaction.txId)
+ onButtonTap: () => _yield.network.openTx(stateAsWaitingTransaction.txId),
),
customIcon: const ZupCircularLoadingIndicator(size: 20),
snackDuration: const Duration(minutes: 10),
- )
- };
- }.call());
+ ),
+ };
+ }.call(),
+ );
});
stream.listen((state) async {
@@ -393,11 +367,7 @@ class PreviewDepositModalCubit extends Cubit with V3Po
(_) async => ScaffoldMessenger.of(context).hideCurrentSnackBar(),
);
- DepositSuccessModal.show(
- context,
- depositedYield: _yield,
- showAsBottomSheet: isMobileSize(context),
- );
+ DepositSuccessModal.show(context, depositedYield: _yield, showAsBottomSheet: isMobileSize(context));
},
orElse: () async {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
diff --git a/lib/app/create/deposit/widgets/token_amount_input_card/token_amount_input_card.dart b/lib/app/create/deposit/widgets/token_amount_input_card/token_amount_input_card.dart
index 814fee2..76e5445 100644
--- a/lib/app/create/deposit/widgets/token_amount_input_card/token_amount_input_card.dart
+++ b/lib/app/create/deposit/widgets/token_amount_input_card/token_amount_input_card.dart
@@ -82,7 +82,7 @@ class _TokenAmountInputCardState extends State with Single
return super.didUpdateWidget(oldWidget);
}
- if (widget.token != oldWidget.token) {
+ if (widget.token != oldWidget.token || widget.network != oldWidget.network) {
WidgetsBinding.instance.addPostFrameCallback((_) {
userBalanceCubit.updateTokenAndNetwork(
widget.token.addresses[widget.network.chainId]!,
diff --git a/lib/core/dtos/pool_search_settings_dto.dart b/lib/core/dtos/pool_search_settings_dto.dart
index bfabbc6..6846618 100644
--- a/lib/core/dtos/pool_search_settings_dto.dart
+++ b/lib/core/dtos/pool_search_settings_dto.dart
@@ -5,7 +5,7 @@ part 'pool_search_settings_dto.g.dart';
@freezed
sealed class PoolSearchSettingsDto with _$PoolSearchSettingsDto {
- static const num defaultMinLiquidityUSD = 1000;
+ static const num defaultMinLiquidityUSD = 5000;
@JsonSerializable(explicitToJson: true)
factory PoolSearchSettingsDto({
@@ -22,7 +22,5 @@ sealed class PoolSearchSettingsDto with _$PoolSearchSettingsDto {
factory PoolSearchSettingsDto.fromJson(Map json) => _$PoolSearchSettingsDtoFromJson(json);
- factory PoolSearchSettingsDto.fixture() => PoolSearchSettingsDto(
- minLiquidityUSD: 1200,
- );
+ factory PoolSearchSettingsDto.fixture() => PoolSearchSettingsDto(minLiquidityUSD: 1200);
}
diff --git a/lib/core/dtos/yield_dto.dart b/lib/core/dtos/yield_dto.dart
index 6b149aa..62627bf 100644
--- a/lib/core/dtos/yield_dto.dart
+++ b/lib/core/dtos/yield_dto.dart
@@ -20,16 +20,18 @@ sealed class YieldDto with _$YieldDto {
required String positionManagerAddress,
required int tickSpacing,
required ProtocolDto protocol,
- required int feeTier,
- required num yield24h,
- required num yield7d,
- required num yield30d,
- required num yield90d,
+ required int initialFeeTier,
+ required int currentFeeTier,
required int chainId,
+ @Default(0) num yield24h,
+ @Default(0) num yield7d,
+ @Default(0) num yield30d,
+ @Default(0) num yield90d,
@Default(PoolType.unknown) @JsonKey(unknownEnumValue: PoolType.unknown) PoolType poolType,
@Default("0") String latestTick,
@Default(0) num totalValueLockedUSD,
@Default(EthereumConstants.zeroAddress) @JsonKey(name: "hooksAddress") String v4Hooks,
+ @Default(EthereumConstants.zeroAddress) @JsonKey(name: "deployerAddress") String deployerAddress,
@JsonKey(name: "poolManagerAddress") String? v4PoolManager,
@JsonKey(name: "stateViewAddress") String? v4StateView,
@JsonKey(name: "permit2Address") String? permit2,
@@ -59,7 +61,8 @@ sealed class YieldDto with _$YieldDto {
factory YieldDto.fromJson(Map json) => _$YieldDtoFromJson(json);
factory YieldDto.fixture() => YieldDto(
- feeTier: 0,
+ initialFeeTier: 0,
+ currentFeeTier: 0,
yield24h: 32.2,
yield30d: 32.2,
yield90d: 32.2,
diff --git a/lib/core/dtos/yields_dto.dart b/lib/core/dtos/yields_dto.dart
index c77a8bd..6a2f2b6 100644
--- a/lib/core/dtos/yields_dto.dart
+++ b/lib/core/dtos/yields_dto.dart
@@ -86,7 +86,8 @@ sealed class YieldsDto with _$YieldsDto {
yield30d: 765.61,
yield90d: 2022.99,
totalValueLockedUSD: 65434567890.21,
- feeTier: 500,
+ initialFeeTier: 500,
+ currentFeeTier: 500,
protocol: ProtocolDto(
id: ProtocolId.pancakeSwapInfinityCL,
rawId: ProtocolId.pancakeSwapInfinityCL.toRawJsonValue,
diff --git a/lib/core/enums/networks.dart b/lib/core/enums/networks.dart
index 428c45b..9ec707c 100644
--- a/lib/core/enums/networks.dart
+++ b/lib/core/enums/networks.dart
@@ -7,134 +7,139 @@ import 'package:zup_app/gen/assets.gen.dart';
enum AppNetworks {
allNetworks,
mainnet,
- // base,
+ base,
+ hyperEvm,
// bnb,
unichain,
scroll,
sepolia;
- static List get testnets => AppNetworks.values
- .where(
- (network) => !network.isAllNetworks && network.isTestnet,
- )
- .toList();
+ static List get testnets =>
+ AppNetworks.values.where((network) => !network.isAllNetworks && network.isTestnet).toList();
- static List get mainnets => AppNetworks.values
- .where(
- (network) => network.isAllNetworks || !network.isTestnet,
- )
- .toList();
+ static List get mainnets =>
+ AppNetworks.values.where((network) => network.isAllNetworks || !network.isTestnet).toList();
static AppNetworks? fromValue(String value) =>
AppNetworks.values.firstWhereOrNull((network) => network.name == value);
- static AppNetworks? fromChainId(int chainId) => AppNetworks.values.firstWhereOrNull(
- (network) {
- if (network.isAllNetworks) return false;
+ static AppNetworks? fromChainId(int chainId) => AppNetworks.values.firstWhereOrNull((network) {
+ if (network.isAllNetworks) return false;
- return int.parse(network.chainInfo.hexChainId) == chainId;
- },
- );
+ return int.parse(network.chainInfo.hexChainId) == chainId;
+ });
int get chainId => int.parse(chainInfo.hexChainId);
bool get isAllNetworks => this == allNetworks;
bool get isTestnet => switch (this) {
- mainnet => false,
- scroll => false,
- sepolia => true,
- allNetworks => false,
- // base => false,
- unichain => false,
- // bnb => false
- };
+ mainnet => false,
+ scroll => false,
+ sepolia => true,
+ allNetworks => false,
+ base => false,
+ unichain => false,
+ hyperEvm => false,
+ // bnb => false
+ };
String get label => switch (this) {
- sepolia => "Sepolia",
- mainnet => "Ethereum",
- scroll => "Scroll",
- allNetworks => "All Networks",
- // base => "Base",
- unichain => "Unichain",
- // bnb => "BNB Chain",
- };
+ sepolia => "Sepolia",
+ mainnet => "Ethereum",
+ scroll => "Scroll",
+ allNetworks => "All Networks",
+ base => "Base",
+ unichain => "Unichain",
+ hyperEvm => "HyperEVM",
+ // bnb => "BNB Chain",
+ };
Widget get icon => switch (this) {
- sepolia => Assets.logos.ethereum.svg(),
- mainnet => Assets.logos.ethereum.svg(),
- scroll => Assets.logos.scroll.svg(),
- // base => Assets.logos.base.svg(),
- unichain => Assets.logos.unichain.svg(),
- allNetworks => Assets.icons.all.svg(),
- // bnb => Assets.logos.bnbChain.svg()
- };
+ sepolia => Assets.logos.ethereum.svg(),
+ mainnet => Assets.logos.ethereum.svg(),
+ scroll => Assets.logos.scroll.svg(),
+ base => Assets.logos.base.svg(),
+ unichain => Assets.logos.unichain.svg(),
+ allNetworks => Assets.icons.all.svg(),
+ hyperEvm => Assets.logos.hyperliquid.svg(),
+ // bnb => Assets.logos.bnbChain.svg()
+ };
ChainInfo get chainInfo => switch (this) {
- allNetworks => throw UnimplementedError("allNetworks is not a valid network"),
- sepolia => ChainInfo(
- hexChainId: "0xaa36a7",
- chainName: label,
- blockExplorerUrls: const ["https://sepolia.etherscan.io"],
- nativeCurrency: NativeCurrencies.eth.currencyInfo,
- rpcUrls: [rpcUrl],
- ),
- mainnet => ChainInfo(
- hexChainId: "0x1",
- chainName: label,
- blockExplorerUrls: const ["https://etherscan.io"],
- nativeCurrency: NativeCurrencies.eth.currencyInfo,
- rpcUrls: [rpcUrl],
- ),
- scroll => ChainInfo(
- hexChainId: "0x82750",
- chainName: label,
- blockExplorerUrls: const ["https://scrollscan.com"],
- nativeCurrency: NativeCurrencies.eth.currencyInfo,
- rpcUrls: [rpcUrl],
- ),
- // base => ChainInfo(
- // hexChainId: "0x2105",
- // chainName: label,
- // blockExplorerUrls: const ["https://basescan.org"],
- // nativeCurrency: NativeCurrencies.eth.currencyInfo,
- // rpcUrls: [rpcUrl],
- // ),
- unichain => ChainInfo(
- hexChainId: "0x82",
- chainName: label,
- blockExplorerUrls: const ["https://uniscan.xyz"],
- nativeCurrency: NativeCurrencies.eth.currencyInfo,
- rpcUrls: [rpcUrl],
- ),
- // bnb => ChainInfo(
- // hexChainId => "0x38",
- // chainName => label,
- // blockExplorerUrls => const ["https://bscscan.com"],
- // nativeCurrency => NativeCurrencies.bnb.currencyInfo,
- // rpcUrls => [rpcUrl],
- // ),
- };
+ allNetworks => throw UnimplementedError("allNetworks is not a valid network"),
+ sepolia => ChainInfo(
+ hexChainId: "0xaa36a7",
+ chainName: label,
+ blockExplorerUrls: const ["https://sepolia.etherscan.io"],
+ nativeCurrency: NativeCurrencies.eth.currencyInfo,
+ rpcUrls: [rpcUrl],
+ ),
+ mainnet => ChainInfo(
+ hexChainId: "0x1",
+ chainName: label,
+ blockExplorerUrls: const ["https://etherscan.io"],
+ nativeCurrency: NativeCurrencies.eth.currencyInfo,
+ rpcUrls: [rpcUrl],
+ ),
+ scroll => ChainInfo(
+ hexChainId: "0x82750",
+ chainName: label,
+ blockExplorerUrls: const ["https://scrollscan.com"],
+ nativeCurrency: NativeCurrencies.eth.currencyInfo,
+ rpcUrls: [rpcUrl],
+ ),
+ base => ChainInfo(
+ hexChainId: "0x2105",
+ chainName: label,
+ blockExplorerUrls: const ["https://basescan.org"],
+ nativeCurrency: NativeCurrencies.eth.currencyInfo,
+ rpcUrls: [rpcUrl],
+ ),
+ unichain => ChainInfo(
+ hexChainId: "0x82",
+ chainName: label,
+ blockExplorerUrls: const ["https://uniscan.xyz"],
+ nativeCurrency: NativeCurrencies.eth.currencyInfo,
+ rpcUrls: [rpcUrl],
+ ),
+ hyperEvm => ChainInfo(
+ hexChainId: "0x3e7",
+ chainName: label,
+ blockExplorerUrls: const ["https://hyperevmscan.io"],
+ nativeCurrency: NativeCurrencies.hype.currencyInfo,
+ rpcUrls: [rpcUrl],
+ ),
+ // bnb => ChainInfo(
+ // hexChainId => "0x38",
+ // chainName => label,
+ // blockExplorerUrls => const ["https://bscscan.com"],
+ // nativeCurrency => NativeCurrencies.bnb.currencyInfo,
+ // rpcUrls => [rpcUrl],
+ // ),
+ };
String get wrappedNativeTokenAddress => switch (this) {
- allNetworks => throw UnimplementedError("allNetworks is not a valid network"),
- sepolia => "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14",
- mainnet => "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
- scroll => "0x5300000000000000000000000000000000000004",
- // base => "0x4200000000000000000000000000000000000006",
- unichain => "0x4200000000000000000000000000000000000006",
- // bnb => "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
- };
+ allNetworks => throw UnimplementedError("allNetworks is not a valid network"),
+ sepolia => "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14",
+ mainnet => "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
+ scroll => "0x5300000000000000000000000000000000000004",
+ base => "0x4200000000000000000000000000000000000006",
+ unichain => "0x4200000000000000000000000000000000000006",
+ hyperEvm => "0x5555555555555555555555555555555555555555",
+ // bnb => "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
+ };
String get rpcUrl => switch (this) {
- allNetworks => throw UnimplementedError("allNetworks is not a valid network"),
- sepolia => "https://ethereum-sepolia-rpc.publicnode.com",
- mainnet => "https://ethereum-rpc.publicnode.com",
- scroll => "https://scroll-rpc.publicnode.com",
- // base => "https://base-rpc.publicnode.com",
- unichain => "https://unichain-rpc.publicnode.com",
- // bnb => "https://bsc-rpc.publicnode.com"
- };
+ allNetworks => throw UnimplementedError("allNetworks is not a valid network"),
+ sepolia => "https://ethereum-sepolia-rpc.publicnode.com",
+ mainnet => "https://ethereum-rpc.publicnode.com",
+ scroll => "https://scroll-rpc.publicnode.com",
+ base => "https://base-rpc.publicnode.com",
+ unichain => "https://unichain-rpc.publicnode.com",
+ hyperEvm => "https://rpc.hyperliquid.xyz/evm",
+ // bnb => "https://bsc-rpc.publicnode.com"
+ };
Future openTx(String txHash) async {
final url = "${chainInfo.blockExplorerUrls?.first}/tx/$txHash";
diff --git a/lib/core/enums/protocol_id.dart b/lib/core/enums/protocol_id.dart
index 529166a..0739bb8 100644
--- a/lib/core/enums/protocol_id.dart
+++ b/lib/core/enums/protocol_id.dart
@@ -4,11 +4,20 @@ part 'protocol_id.g.dart';
@JsonEnum(alwaysCreate: true)
enum ProtocolId {
- @JsonValue("pancake-v4-cl")
+ @JsonValue("pancakeswap-infinity-cl")
pancakeSwapInfinityCL,
+ @JsonValue("aerodrome-v3")
+ aerodromeSlipstream,
+ @JsonValue("velodrome-v3")
+ velodromeSlipstream,
+ @JsonValue("gliquid-v3")
+ gliquidV3,
unknown;
bool get isPancakeSwapInfinityCL => this == ProtocolId.pancakeSwapInfinityCL;
+ bool get isAerodromeOrVelodromeSlipstream =>
+ (this == ProtocolId.aerodromeSlipstream || this == ProtocolId.velodromeSlipstream);
+ bool get isGLiquidV3 => this == ProtocolId.gliquidV3;
String get toRawJsonValue => _$ProtocolIdEnumMap[this]!;
}
diff --git a/lib/core/injections.dart b/lib/core/injections.dart
index 1574f35..87d9b79 100644
--- a/lib/core/injections.dart
+++ b/lib/core/injections.dart
@@ -6,8 +6,13 @@ import 'package:get_it/get_it.dart';
import 'package:lottie/lottie.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:web3kit/web3kit.dart';
+import 'package:zup_app/abis/aerodrome_v3_pool.abi.g.dart';
+import 'package:zup_app/abis/aerodrome_v3_position_manager.abi.g.dart';
+import 'package:zup_app/abis/algebra/v1.2.1/pool.abi.g.dart' as algebra_1_2_1_pool;
+import 'package:zup_app/abis/algebra/v1.2.1/position_manager.abi.g.dart' as algebra_1_2_1_position_manager;
import 'package:zup_app/abis/erc_20.abi.g.dart';
import 'package:zup_app/abis/pancake_swap_infinity_cl_pool_manager.abi.g.dart';
+import 'package:zup_app/abis/pancake_swap_infinity_cl_position_manager.abi.g.dart';
import 'package:zup_app/abis/uniswap_permit2.abi.g.dart';
import 'package:zup_app/abis/uniswap_v3_pool.abi.g.dart';
import 'package:zup_app/abis/uniswap_v3_position_manager.abi.g.dart';
@@ -126,6 +131,18 @@ Future setupInjections() async {
inject.registerLazySingleton(() => PancakeSwapInfinityClPoolManager());
+ inject.registerLazySingleton(() => AerodromeV3PositionManager());
+
+ inject.registerLazySingleton(() => AerodromeV3Pool());
+
+ inject.registerLazySingleton(() => algebra_1_2_1_pool.Pool());
+
+ inject.registerLazySingleton(
+ () => algebra_1_2_1_position_manager.PositionManager(),
+ );
+
+ inject.registerLazySingleton(() => PancakeSwapInfinityClPositionManager());
+
inject.registerLazySingleton(
() => PoolService(
inject(),
@@ -134,6 +151,11 @@ Future setupInjections() async {
inject(),
inject(),
inject(),
+ inject(),
+ inject(),
+ inject(),
+ inject(),
+ inject(),
),
);
diff --git a/lib/core/pool_service.dart b/lib/core/pool_service.dart
index 02a0d76..0c78fa8 100644
--- a/lib/core/pool_service.dart
+++ b/lib/core/pool_service.dart
@@ -1,7 +1,12 @@
import 'package:clock/clock.dart';
import 'package:web3kit/core/dtos/transaction_response.dart';
import 'package:web3kit/web3kit.dart';
+import 'package:zup_app/abis/aerodrome_v3_pool.abi.g.dart';
+import 'package:zup_app/abis/aerodrome_v3_position_manager.abi.g.dart';
+import 'package:zup_app/abis/algebra/v1.2.1/pool.abi.g.dart' as algebra_1_2_1_pool;
+import 'package:zup_app/abis/algebra/v1.2.1/position_manager.abi.g.dart' as algebra_1_2_1_position_manager;
import 'package:zup_app/abis/pancake_swap_infinity_cl_pool_manager.abi.g.dart';
+import 'package:zup_app/abis/pancake_swap_infinity_cl_position_manager.abi.g.dart';
import 'package:zup_app/abis/uniswap_v3_pool.abi.g.dart';
import 'package:zup_app/abis/uniswap_v3_position_manager.abi.g.dart';
import 'package:zup_app/abis/uniswap_v4_position_manager.abi.g.dart';
@@ -17,6 +22,11 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
final UniswapV4PositionManager _uniswapV4PositionManager;
final EthereumAbiCoder _ethereumAbiCoder;
final PancakeSwapInfinityClPoolManager _pancakeSwapInfinityClPoolManager;
+ final PancakeSwapInfinityClPositionManager _pancakeSwapInfinityClPositionManager;
+ final AerodromeV3PositionManager _aerodromeV3PositionManager;
+ final AerodromeV3Pool _aerodromeV3Pool;
+ final algebra_1_2_1_pool.Pool _algebra121Pool;
+ final algebra_1_2_1_position_manager.PositionManager _algebra121PositionManager;
PoolService(
this._uniswapV4StateView,
@@ -25,9 +35,23 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
this._uniswapV4PositionManager,
this._ethereumAbiCoder,
this._pancakeSwapInfinityClPoolManager,
+ this._pancakeSwapInfinityClPositionManager,
+ this._aerodromeV3PositionManager,
+ this._aerodromeV3Pool,
+ this._algebra121Pool,
+ this._algebra121PositionManager,
);
Future getPoolTick(YieldDto forYield) async {
+ if (forYield.protocol.id.isGLiquidV3) {
+ final algebraPool = _algebra121Pool.fromRpcProvider(
+ contractAddress: forYield.poolAddress,
+ rpcUrl: forYield.network.rpcUrl,
+ );
+
+ return (await algebraPool.globalState()).tick;
+ }
+
if (forYield.protocol.id.isPancakeSwapInfinityCL) {
final pancakeSwapInfinityCLPoolManagerContract = _pancakeSwapInfinityClPoolManager.fromRpcProvider(
contractAddress: forYield.v4PoolManager!,
@@ -37,6 +61,15 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
return (await pancakeSwapInfinityCLPoolManagerContract.getSlot0(id: forYield.poolAddress)).tick;
}
+ if (forYield.protocol.id.isAerodromeOrVelodromeSlipstream) {
+ final aerodromeV3Pool = _aerodromeV3Pool.fromRpcProvider(
+ contractAddress: forYield.poolAddress,
+ rpcUrl: forYield.network.rpcUrl,
+ );
+
+ return (await aerodromeV3Pool.slot0()).tick;
+ }
+
if (forYield.poolType.isV4) {
final stateView = _uniswapV4StateView.fromRpcProvider(
contractAddress: forYield.v4StateView!,
@@ -64,6 +97,24 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
return (await pancakeSwapInfinityCLPoolManagerContract.getSlot0(id: forYield.poolAddress)).sqrtPriceX96;
}
+ if (forYield.protocol.id.isGLiquidV3) {
+ final algebraPool = _algebra121Pool.fromRpcProvider(
+ contractAddress: forYield.poolAddress,
+ rpcUrl: forYield.network.rpcUrl,
+ );
+
+ return (await algebraPool.globalState()).price;
+ }
+
+ if (forYield.protocol.id.isAerodromeOrVelodromeSlipstream) {
+ final aerodromeV3Pool = _aerodromeV3Pool.fromRpcProvider(
+ contractAddress: forYield.poolAddress,
+ rpcUrl: forYield.network.rpcUrl,
+ );
+
+ return (await aerodromeV3Pool.slot0()).sqrtPriceX96;
+ }
+
if (forYield.poolType.isV4) {
final stateView = _uniswapV4StateView.fromRpcProvider(
contractAddress: forYield.v4StateView!,
@@ -97,6 +148,36 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
required BigInt tickLower,
required BigInt tickUpper,
}) async {
+ if (depositOnYield.protocol.id.isAerodromeOrVelodromeSlipstream) {
+ return _sendV3DepositTransactionForSlipstream(
+ depositOnYield,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+ }
+
+ if (depositOnYield.protocol.id.isGLiquidV3) {
+ return _sendV3DepositTransactionForAlgebra121(
+ depositOnYield,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+ }
+
final v3PositionManagerContract = _uniswapV3PositionManager.fromSigner(
contractAddress: depositOnYield.positionManagerAddress,
signer: signer,
@@ -114,28 +195,22 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
recipient: recipient,
tickLower: tickLower,
tickUpper: tickUpper,
- fee: BigInt.from(depositOnYield.feeTier),
- token0: depositOnYield.token0.addresses[depositOnYield.network.chainId]! == EthereumConstants.zeroAddress
- ? depositOnYield.network.wrappedNativeTokenAddress
- : depositOnYield.token0.addresses[depositOnYield.network.chainId]!,
- token1: depositOnYield.token1.addresses[depositOnYield.network.chainId]! == EthereumConstants.zeroAddress
- ? depositOnYield.network.wrappedNativeTokenAddress
- : depositOnYield.token1.addresses[depositOnYield.network.chainId]!,
+ fee: BigInt.from(depositOnYield.initialFeeTier),
+ token0: _getNativeV3PoolToken0Address(depositOnYield),
+ token1: _getNativeV3PoolToken1Address(depositOnYield),
),
);
return await v3PositionManagerContract.multicall(
- data: [
- mintCalldata,
- _uniswapV3PositionManager.getRefundETHCalldata(),
- ],
- ethValue: () {
- if (depositOnYield.isToken0Native) {
- return amount0Desired;
- }
-
- return amount1Desired;
- }.call());
+ data: [mintCalldata, _uniswapV3PositionManager.getRefundETHCalldata()],
+ ethValue: () {
+ if (depositOnYield.isToken0Native) {
+ return amount0Desired;
+ }
+
+ return amount1Desired;
+ }.call(),
+ );
}
return await v3PositionManagerContract.mint(
@@ -148,7 +223,7 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
recipient: recipient,
tickLower: tickLower,
tickUpper: tickUpper,
- fee: BigInt.from(depositOnYield.feeTier),
+ fee: BigInt.from(depositOnYield.initialFeeTier),
token0: depositOnYield.token0.addresses[depositOnYield.network.chainId]!,
token1: depositOnYield.token1.addresses[depositOnYield.network.chainId]!,
),
@@ -170,6 +245,21 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
required BigInt maxAmount1ToDeposit,
required String recipient,
}) async {
+ if (depositOnYield.protocol.id.isPancakeSwapInfinityCL) {
+ return _sendV4PoolDepositTransactionForPancakeSwap(
+ depositOnYield,
+ signer,
+ deadline: deadline,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ amount0toDeposit: amount0toDeposit,
+ amount1ToDeposit: amount1ToDeposit,
+ maxAmount0ToDeposit: maxAmount0ToDeposit,
+ maxAmount1ToDeposit: maxAmount1ToDeposit,
+ recipient: recipient,
+ );
+ }
+
final isNativeDeposit = depositOnYield.isToken0Native || depositOnYield.isToken1Native;
final sqrtPriceX96 = await getSqrtPriceX96(depositOnYield);
final sqrtPriceAX96 = getSqrtPriceAtTick(tickLower);
@@ -182,58 +272,54 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
amount1ToDeposit,
);
- final actions = _ethereumAbiCoder.encodePacked([
- "uint8",
- "uint8",
- if (isNativeDeposit) "uint8",
- ], [
- V4PoolConstants.mintPositionActionValue,
- V4PoolConstants.settlePairActionValue,
- if (isNativeDeposit) V4PoolConstants.sweepActionValue,
- ]);
-
- final mintPositionActionParams = _ethereumAbiCoder.encode([
- "tuple(address,address,int32,int24,address)",
- "int24",
- "int24",
- "uint256",
- "uint128",
- "uint128",
- "address",
- "bytes"
- ], [
+ final actions = _ethereumAbiCoder.encodePacked(
+ ["uint8", "uint8", if (isNativeDeposit) "uint8"],
+ [
+ V4PoolConstants.mintPositionActionValue,
+ V4PoolConstants.uniswapSettlePairActionValue,
+ if (isNativeDeposit) V4PoolConstants.uniswapSweepActionValue,
+ ],
+ );
+
+ final mintPositionActionParams = _ethereumAbiCoder.encode(
+ [
+ "tuple(address,address,int32,int24,address)",
+ "int24",
+ "int24",
+ "uint256",
+ "uint128",
+ "uint128",
+ "address",
+ "bytes",
+ ],
+ [
+ [
+ depositOnYield.token0.addresses[depositOnYield.network.chainId]!,
+ depositOnYield.token1.addresses[depositOnYield.network.chainId]!,
+ BigInt.from(depositOnYield.initialFeeTier),
+ BigInt.from(depositOnYield.tickSpacing),
+ depositOnYield.v4Hooks,
+ ],
+ tickLower,
+ tickUpper,
+ liquidity,
+ depositOnYield.isToken0Native ? amount0toDeposit : maxAmount0ToDeposit,
+ depositOnYield.isToken1Native ? amount1ToDeposit : maxAmount1ToDeposit,
+ recipient,
+ EthereumConstants.emptyBytes,
+ ],
+ );
+
+ final settlePairActionParams = _ethereumAbiCoder.encode(
+ ["address", "address"],
[
depositOnYield.token0.addresses[depositOnYield.network.chainId]!,
depositOnYield.token1.addresses[depositOnYield.network.chainId]!,
- BigInt.from(depositOnYield.feeTier),
- BigInt.from(depositOnYield.tickSpacing),
- depositOnYield.v4Hooks,
],
- tickLower,
- tickUpper,
- liquidity,
- depositOnYield.isToken0Native ? amount0toDeposit : maxAmount0ToDeposit,
- depositOnYield.isToken1Native ? amount1ToDeposit : maxAmount1ToDeposit,
- recipient,
- EthereumConstants.emptyBytes,
- ]);
-
- final settlePairActionParams = _ethereumAbiCoder.encode([
- "address",
- "address"
- ], [
- depositOnYield.token0.addresses[depositOnYield.network.chainId]!,
- depositOnYield.token1.addresses[depositOnYield.network.chainId]!,
- ]);
+ );
final sweepActionParams = isNativeDeposit
- ? _ethereumAbiCoder.encode([
- "address",
- "address"
- ], [
- EthereumConstants.zeroAddress,
- recipient,
- ])
+ ? _ethereumAbiCoder.encode(["address", "address"], [EthereumConstants.zeroAddress, recipient])
: null;
final uniswapV4PositionManagerContract = _uniswapV4PositionManager.fromSigner(
@@ -241,19 +327,9 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
signer: signer,
);
- final params = [
- mintPositionActionParams,
- settlePairActionParams,
- if (isNativeDeposit) sweepActionParams,
- ];
+ final params = [mintPositionActionParams, settlePairActionParams, if (isNativeDeposit) sweepActionParams];
- final unlockData = _ethereumAbiCoder.encode([
- "bytes",
- "bytes[]"
- ], [
- actions,
- params,
- ]);
+ final unlockData = _ethereumAbiCoder.encode(["bytes", "bytes[]"], [actions, params]);
return await uniswapV4PositionManagerContract.modifyLiquidities(
deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
@@ -266,4 +342,246 @@ class PoolService with V4PoolLiquidityCalculationsMixin {
}.call(),
);
}
+
+ Future _sendV4PoolDepositTransactionForPancakeSwap(
+ YieldDto depositOnYield,
+ Signer signer, {
+ required Duration deadline,
+ required BigInt tickLower,
+ required BigInt tickUpper,
+ required BigInt amount0toDeposit,
+ required BigInt amount1ToDeposit,
+ required BigInt maxAmount0ToDeposit,
+ required BigInt maxAmount1ToDeposit,
+ required String recipient,
+ }) async {
+ final isNativeDeposit = depositOnYield.isToken0Native || depositOnYield.isToken1Native;
+ final sqrtPriceX96 = await getSqrtPriceX96(depositOnYield);
+ final sqrtPriceAX96 = getSqrtPriceAtTick(tickLower);
+ final sqrtPriceBX96 = getSqrtPriceAtTick(tickUpper);
+ final liquidity = getLiquidityForAmounts(
+ sqrtPriceX96,
+ sqrtPriceAX96,
+ sqrtPriceBX96,
+ amount0toDeposit,
+ amount1ToDeposit,
+ );
+
+ final actions = _ethereumAbiCoder.encodePacked(
+ ["uint8", "uint8", "uint8"],
+ [
+ V4PoolConstants.mintPositionActionValue,
+ V4PoolConstants.pancakeSwapCloseCurrencyActionValue,
+ V4PoolConstants.pancakeSwapCloseCurrencyActionValue,
+ ],
+ );
+
+ final mintPositionActionParams = _ethereumAbiCoder.encode(
+ [
+ "tuple(address,address,address,address,uint24,bytes32)",
+ "int24",
+ "int24",
+ "uint256",
+ "uint128",
+ "uint128",
+ "address",
+ "bytes",
+ ],
+ [
+ [
+ depositOnYield.token0.addresses[depositOnYield.network.chainId]!,
+ depositOnYield.token1.addresses[depositOnYield.network.chainId]!,
+ depositOnYield.v4Hooks,
+ depositOnYield.v4PoolManager,
+ depositOnYield.initialFeeTier,
+ await _getPancakeSwapInfinityPoolBytesParameters(depositOnYield),
+ ],
+ tickLower,
+ tickUpper,
+ liquidity,
+ depositOnYield.isToken0Native ? amount0toDeposit : maxAmount0ToDeposit,
+ depositOnYield.isToken1Native ? amount1ToDeposit : maxAmount1ToDeposit,
+ recipient,
+ EthereumConstants.emptyBytes,
+ ],
+ );
+
+ final closeCurrency0ActionParams = _ethereumAbiCoder.encode(
+ ["address"],
+ [depositOnYield.token0.addresses[depositOnYield.network.chainId]!],
+ );
+
+ final closeCurrency1ActionParams = _ethereumAbiCoder.encode(
+ ["address"],
+ [depositOnYield.token1.addresses[depositOnYield.network.chainId]!],
+ );
+
+ final pancakeSwapV4PositionManagerContract = _pancakeSwapInfinityClPositionManager.fromSigner(
+ contractAddress: depositOnYield.positionManagerAddress,
+ signer: signer,
+ );
+
+ final params = [mintPositionActionParams, closeCurrency0ActionParams, closeCurrency1ActionParams];
+ final payloadData = _ethereumAbiCoder.encode(["bytes", "bytes[]"], [actions, params]);
+
+ return await pancakeSwapV4PositionManagerContract.modifyLiquidities(
+ deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
+ payload: payloadData,
+ ethValue: () {
+ if (!isNativeDeposit) return null;
+ if (depositOnYield.isToken0Native) return amount0toDeposit;
+
+ return amount1ToDeposit;
+ }.call(),
+ );
+ }
+
+ Future _sendV3DepositTransactionForAlgebra121(
+ YieldDto depositOnYield,
+ Signer signer, {
+ required BigInt amount0Desired,
+ required BigInt amount1Desired,
+ required Duration deadline,
+ required BigInt amount0Min,
+ required BigInt amount1Min,
+ required String recipient,
+ required BigInt tickLower,
+ required BigInt tickUpper,
+ }) async {
+ final positionManagerContract = _algebra121PositionManager.fromSigner(
+ contractAddress: depositOnYield.positionManagerAddress,
+ signer: signer,
+ );
+ final TransactionResponse tx = await () async {
+ if (depositOnYield.isToken1Native || depositOnYield.isToken0Native) {
+ final mintCalldata = _algebra121PositionManager.getMintCalldata(
+ params: (
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ deployer: depositOnYield.deployerAddress,
+ token0: _getNativeV3PoolToken0Address(depositOnYield),
+ token1: _getNativeV3PoolToken1Address(depositOnYield),
+ ),
+ );
+
+ return await positionManagerContract.multicall(
+ data: [mintCalldata, _algebra121PositionManager.getRefundNativeTokenCalldata()],
+ ethValue: () {
+ if (depositOnYield.isToken0Native) return amount0Desired;
+
+ return amount1Desired;
+ }.call(),
+ );
+ }
+
+ return await positionManagerContract.mint(
+ params: (
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ deployer: depositOnYield.deployerAddress,
+ token0: depositOnYield.token0.addresses[depositOnYield.network.chainId]!,
+ token1: depositOnYield.token1.addresses[depositOnYield.network.chainId]!,
+ ),
+ );
+ }.call();
+
+ return tx;
+ }
+
+ Future _sendV3DepositTransactionForSlipstream(
+ YieldDto depositOnYield,
+ Signer signer, {
+ required BigInt amount0Desired,
+ required BigInt amount1Desired,
+ required Duration deadline,
+ required BigInt amount0Min,
+ required BigInt amount1Min,
+ required String recipient,
+ required BigInt tickLower,
+ required BigInt tickUpper,
+ }) async {
+ final aerodromeV3PositionManager = _aerodromeV3PositionManager.fromSigner(
+ contractAddress: depositOnYield.positionManagerAddress,
+ signer: signer,
+ );
+
+ final TransactionResponse tx = await () async {
+ if (depositOnYield.isToken1Native || depositOnYield.isToken0Native) {
+ final mintCalldata = _aerodromeV3PositionManager.getMintCalldata(
+ params: (
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ tickSpacing: BigInt.from(depositOnYield.tickSpacing),
+ sqrtPriceX96: BigInt.from(0),
+ token0: _getNativeV3PoolToken0Address(depositOnYield),
+ token1: _getNativeV3PoolToken1Address(depositOnYield),
+ ),
+ );
+
+ return await aerodromeV3PositionManager.multicall(
+ data: [mintCalldata, _aerodromeV3PositionManager.getRefundETHCalldata()],
+ ethValue: () {
+ if (depositOnYield.isToken0Native) return amount0Desired;
+ return amount1Desired;
+ }.call(),
+ );
+ }
+
+ return await aerodromeV3PositionManager.mint(
+ params: (
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ tickSpacing: BigInt.from(depositOnYield.tickSpacing),
+ sqrtPriceX96: BigInt.from(0),
+ token0: depositOnYield.token0.addresses[depositOnYield.network.chainId]!,
+ token1: depositOnYield.token1.addresses[depositOnYield.network.chainId]!,
+ ),
+ );
+ }.call();
+
+ return tx;
+ }
+
+ String _getNativeV3PoolToken0Address(YieldDto forYield) {
+ if (forYield.isToken0Native) return forYield.network.wrappedNativeTokenAddress;
+ return forYield.token0.addresses[forYield.network.chainId]!;
+ }
+
+ String _getNativeV3PoolToken1Address(YieldDto forYield) {
+ if (forYield.isToken1Native) return forYield.network.wrappedNativeTokenAddress;
+ return forYield.token1.addresses[forYield.network.chainId]!;
+ }
+
+ Future _getPancakeSwapInfinityPoolBytesParameters(YieldDto forYield) async {
+ final contract = _pancakeSwapInfinityClPoolManager.fromRpcProvider(
+ contractAddress: forYield.v4PoolManager!,
+ rpcUrl: forYield.network.rpcUrl,
+ );
+
+ return (await contract.poolIdToPoolKey(id: forYield.poolAddress)).parameters;
+ }
}
diff --git a/lib/core/v4_pool_constants.dart b/lib/core/v4_pool_constants.dart
index 75ad585..22b3285 100644
--- a/lib/core/v4_pool_constants.dart
+++ b/lib/core/v4_pool_constants.dart
@@ -1,5 +1,6 @@
abstract class V4PoolConstants {
static const mintPositionActionValue = 0x02;
- static const settlePairActionValue = 0x0d;
- static const sweepActionValue = 0x14;
+ static const uniswapSettlePairActionValue = 0x0d;
+ static const uniswapSweepActionValue = 0x14;
+ static const pancakeSwapCloseCurrencyActionValue = 0x12;
}
diff --git a/lib/l10n/en.arb b/lib/l10n/en.arb
index 21fac94..645db5e 100644
--- a/lib/l10n/en.arb
+++ b/lib/l10n/en.arb
@@ -166,7 +166,7 @@
}
}
},
- "yieldCardAverageYieldYearly": "Average Yield (Yearly)",
+ "yieldCardAverageYieldYearly": "Average Yearly Yield",
"previewDepositModalDepositSuccessSnackBarHelperButtonTitle": "View Transaction",
"previewDepositModalApproveSuccessSnackBarHelperButtonTitle": "View Transaction",
"previewDepositModalWaitingTransactionSnackBarHelperButtonTitle": "View on Explorer",
diff --git a/lib/l10n/gen/app_localizations.dart b/lib/l10n/gen/app_localizations.dart
index cba7dfa..70efcef 100644
--- a/lib/l10n/gen/app_localizations.dart
+++ b/lib/l10n/gen/app_localizations.dart
@@ -463,7 +463,7 @@ abstract class S {
/// No description provided for @yieldCardAverageYieldYearly.
///
/// In en, this message translates to:
- /// **'Average Yield (Yearly)'**
+ /// **'Average Yearly Yield'**
String get yieldCardAverageYieldYearly;
/// No description provided for @previewDepositModalDepositSuccessSnackBarHelperButtonTitle.
diff --git a/lib/l10n/gen/app_localizations_en.dart b/lib/l10n/gen/app_localizations_en.dart
index b21bec5..12e0b97 100644
--- a/lib/l10n/gen/app_localizations_en.dart
+++ b/lib/l10n/gen/app_localizations_en.dart
@@ -237,7 +237,7 @@ class SEn extends S {
}
@override
- String get yieldCardAverageYieldYearly => 'Average Yield (Yearly)';
+ String get yieldCardAverageYieldYearly => 'Average Yearly Yield';
@override
String get previewDepositModalDepositSuccessSnackBarHelperButtonTitle =>
diff --git a/lib/widgets/token_selector_modal/token_selector_modal_cubit.dart b/lib/widgets/token_selector_modal/token_selector_modal_cubit.dart
index 2f21409..91fa325 100644
--- a/lib/widgets/token_selector_modal/token_selector_modal_cubit.dart
+++ b/lib/widgets/token_selector_modal/token_selector_modal_cubit.dart
@@ -13,15 +13,16 @@ part 'token_selector_modal_state.dart';
class TokenSelectorModalCubit extends Cubit {
TokenSelectorModalCubit(this._tokensRepository, this._appCubit, this._wallet)
- : super(const TokenSelectorModalState.initial());
+ : super(const TokenSelectorModalState.initial());
final TokensRepository _tokensRepository;
final AppCubit _appCubit;
final Wallet _wallet;
final Map> _tokenListCachedPerNetworkByAddress = {};
- Future get tokenList async => _tokenListCachedPerNetworkByAddress[_appCubit.selectedNetwork]
- ?[await _wallet.signer?.address ?? EthereumConstants.zeroAddress];
+ Future get tokenList async =>
+ _tokenListCachedPerNetworkByAddress[_appCubit.selectedNetwork]?[await _wallet.signer?.address ??
+ EthereumConstants.zeroAddress];
Future _emitSuccessCached() async => emit(TokenSelectorModalState.success((await tokenList)!));
bool get _shouldDiscardSearchState => state != const TokenSelectorModalState.searchLoading();
@@ -41,8 +42,8 @@ class TokenSelectorModalCubit extends Cubit {
try {
emit(const TokenSelectorModalState.loading());
- _tokenListCachedPerNetworkByAddress[_appCubit.selectedNetwork]![userAddress] =
- await _tokensRepository.getTokenList(_appCubit.selectedNetwork);
+ _tokenListCachedPerNetworkByAddress[_appCubit.selectedNetwork]![userAddress] = await _tokensRepository
+ .getTokenList(_appCubit.selectedNetwork);
if (_shouldDiscardTokenListLoadedState) return;
diff --git a/lib/widgets/yield_card.dart b/lib/widgets/yield_card.dart
index 8bf4742..5d33386 100644
--- a/lib/widgets/yield_card.dart
+++ b/lib/widgets/yield_card.dart
@@ -88,7 +88,9 @@ class _YieldCardState extends State {
Padding(
padding: const EdgeInsets.only(top: 10),
child: Text(
- S.of(context).yieldCardYearlyYield,
+ widget.timeFrame.isDay
+ ? S.of(context).yieldCardYearlyYield
+ : S.of(context).yieldCardAverageYieldYearly,
style: TextStyle(fontSize: 14, color: ZupThemeColors.primaryText.themed(context.brightness)),
),
),
diff --git a/lib/widgets/zup_cached_image.dart b/lib/widgets/zup_cached_image.dart
index cb02398..d135b8f 100644
--- a/lib/widgets/zup_cached_image.dart
+++ b/lib/widgets/zup_cached_image.dart
@@ -39,7 +39,12 @@ class ZupCachedImage {
fit: BoxFit.cover,
errorBuilder: errorWidget,
frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
- if (frame == null) return placeholder ?? ZupCircularLoadingIndicator(size: height ?? 20);
+ if (frame == null) {
+ return Container(
+ color: ZupThemeColors.background.themed(context.brightness),
+ child: placeholder ?? ZupCircularLoadingIndicator(size: height ?? 20),
+ );
+ }
return child;
},
webHtmlElementStrategy: WebHtmlElementStrategy.fallback,
diff --git a/pubspec.lock b/pubspec.lock
index 8e6c9f0..209b05c 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1281,7 +1281,7 @@ packages:
description:
path: "."
ref: main
- resolved-ref: "13ec43de31406f3f5195f6747474ccb50eacdf8e"
+ resolved-ref: "9a51f58425d80bd29886286a68571d653b4995d5"
url: "https://github.com/Zup-Protocol/web3kit.git"
source: git
version: "0.0.1"
@@ -1339,7 +1339,7 @@ packages:
description:
path: "."
ref: main
- resolved-ref: "311aa04082ab0b85f2e8dc351777176338a227ea"
+ resolved-ref: ce5f6541493ed80ad96b2ee3adf75ad67c9a1e59
url: "https://github.com/Zup-Protocol/zup-ui-kit.git"
source: git
version: "0.0.1"
diff --git a/test/app/create/deposit/goldens/deposit_page_30d_timeframe.png b/test/app/create/deposit/goldens/deposit_page_30d_timeframe.png
index 4df6120..e712388 100644
Binary files a/test/app/create/deposit/goldens/deposit_page_30d_timeframe.png and b/test/app/create/deposit/goldens/deposit_page_30d_timeframe.png differ
diff --git a/test/app/create/deposit/goldens/deposit_page_7d_timeframe.png b/test/app/create/deposit/goldens/deposit_page_7d_timeframe.png
index 35b7dac..8156917 100644
Binary files a/test/app/create/deposit/goldens/deposit_page_7d_timeframe.png and b/test/app/create/deposit/goldens/deposit_page_7d_timeframe.png differ
diff --git a/test/app/create/deposit/goldens/deposit_page_90d_timeframe.png b/test/app/create/deposit/goldens/deposit_page_90d_timeframe.png
index ce292d7..8f2b63d 100644
Binary files a/test/app/create/deposit/goldens/deposit_page_90d_timeframe.png and b/test/app/create/deposit/goldens/deposit_page_90d_timeframe.png differ
diff --git a/test/app/create/deposit/goldens/deposit_page_pools_page_1_30d_timeframe.png b/test/app/create/deposit/goldens/deposit_page_pools_page_1_30d_timeframe.png
index 229945c..a4316e3 100644
Binary files a/test/app/create/deposit/goldens/deposit_page_pools_page_1_30d_timeframe.png and b/test/app/create/deposit/goldens/deposit_page_pools_page_1_30d_timeframe.png differ
diff --git a/test/app/create/deposit/goldens/deposit_page_pools_page_1_7d_timeframe.png b/test/app/create/deposit/goldens/deposit_page_pools_page_1_7d_timeframe.png
index b476194..908b7e1 100644
Binary files a/test/app/create/deposit/goldens/deposit_page_pools_page_1_7d_timeframe.png and b/test/app/create/deposit/goldens/deposit_page_pools_page_1_7d_timeframe.png differ
diff --git a/test/app/create/deposit/goldens/deposit_page_pools_page_1_90d_timeframe.png b/test/app/create/deposit/goldens/deposit_page_pools_page_1_90d_timeframe.png
index 104e1e0..7aa1453 100644
Binary files a/test/app/create/deposit/goldens/deposit_page_pools_page_1_90d_timeframe.png and b/test/app/create/deposit/goldens/deposit_page_pools_page_1_90d_timeframe.png differ
diff --git a/test/app/create/deposit/goldens/deposit_page_pools_page_2_30d_timeframe.png b/test/app/create/deposit/goldens/deposit_page_pools_page_2_30d_timeframe.png
index 60c5dde..61fdc95 100644
Binary files a/test/app/create/deposit/goldens/deposit_page_pools_page_2_30d_timeframe.png and b/test/app/create/deposit/goldens/deposit_page_pools_page_2_30d_timeframe.png differ
diff --git a/test/app/create/deposit/goldens/deposit_page_pools_page_2_7d_timeframe.png b/test/app/create/deposit/goldens/deposit_page_pools_page_2_7d_timeframe.png
index ba99362..e7de6c4 100644
Binary files a/test/app/create/deposit/goldens/deposit_page_pools_page_2_7d_timeframe.png and b/test/app/create/deposit/goldens/deposit_page_pools_page_2_7d_timeframe.png differ
diff --git a/test/app/create/deposit/goldens/deposit_page_pools_page_2_90d_timeframe.png b/test/app/create/deposit/goldens/deposit_page_pools_page_2_90d_timeframe.png
index eec31e2..7b2c6bd 100644
Binary files a/test/app/create/deposit/goldens/deposit_page_pools_page_2_90d_timeframe.png and b/test/app/create/deposit/goldens/deposit_page_pools_page_2_90d_timeframe.png differ
diff --git a/test/app/create/deposit/goldens/deposit_page_reset_scroll_position_on_timeframe_change.png b/test/app/create/deposit/goldens/deposit_page_reset_scroll_position_on_timeframe_change.png
index 5f44a12..6cd6fbe 100644
Binary files a/test/app/create/deposit/goldens/deposit_page_reset_scroll_position_on_timeframe_change.png and b/test/app/create/deposit/goldens/deposit_page_reset_scroll_position_on_timeframe_change.png differ
diff --git a/test/app/create/deposit/widgets/token_amount_input_card/token_amount_input_card_test.dart b/test/app/create/deposit/widgets/token_amount_input_card/token_amount_input_card_test.dart
index 56ee9b9..8250d71 100644
--- a/test/app/create/deposit/widgets/token_amount_input_card/token_amount_input_card_test.dart
+++ b/test/app/create/deposit/widgets/token_amount_input_card/token_amount_input_card_test.dart
@@ -380,6 +380,39 @@ void main() {
},
);
+ zGoldenTest(
+ """When updating the widget from one network, for a different network,
+ it should update the token in the cubit and get the balance again""",
+ (tester) async {
+ await tester.runAsync(() async {
+ const key = Key("token-amount-card");
+
+ const oldTokenNetwork = AppNetworks.scroll;
+ const newTokenNetwork = AppNetworks.sepolia;
+
+ final token = TokenDto.fixture().copyWith(
+ addresses: {
+ AppNetworks.scroll.chainId: AppNetworks.scroll.wrappedNativeTokenAddress,
+ AppNetworks.sepolia.chainId: AppNetworks.sepolia.wrappedNativeTokenAddress,
+ },
+ symbol: "OLD_TOKEN",
+ );
+
+ await tester.pumpDeviceBuilder(
+ await goldenBuilder(key: key, token: token, isNative: false, network: oldTokenNetwork),
+ );
+ await tester.pumpDeviceBuilder(
+ await goldenBuilder(key: key, token: token, isNative: false, network: newTokenNetwork),
+ );
+ await tester.pumpAndSettle();
+
+ verify(
+ () => wallet.nativeOrTokenBalance(token.addresses[newTokenNetwork.chainId]!, rpcUrl: newTokenNetwork.rpcUrl),
+ ).called(1);
+ });
+ },
+ );
+
zGoldenTest(
"""When there's a large number typed, it should not hard clip it in the left border,
but instead do a soft clip with a gradient""",
diff --git a/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_open.png b/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_open.png
index ed02df2..48a39a6 100644
Binary files a/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_open.png and b/test/app/create/goldens/create_page_select_tokens_stage_pool_search_settings_open.png differ
diff --git a/test/app/create/widgets/goldens/create_page_setting_dropdown_min_liquidity_non_numeric.png b/test/app/create/widgets/goldens/create_page_setting_dropdown_min_liquidity_non_numeric.png
index 24c1d1a..fa4de39 100644
Binary files a/test/app/create/widgets/goldens/create_page_setting_dropdown_min_liquidity_non_numeric.png and b/test/app/create/widgets/goldens/create_page_setting_dropdown_min_liquidity_non_numeric.png differ
diff --git a/test/app/create/widgets/goldens/create_page_settings_dropdown_low_min_tvl_warning.png b/test/app/create/widgets/goldens/create_page_settings_dropdown_low_min_tvl_warning.png
index d98d333..6ccfd89 100644
Binary files a/test/app/create/widgets/goldens/create_page_settings_dropdown_low_min_tvl_warning.png and b/test/app/create/widgets/goldens/create_page_settings_dropdown_low_min_tvl_warning.png differ
diff --git a/test/app/create/widgets/goldens/create_page_settings_dropdown_min_liquidity_tooltip.png b/test/app/create/widgets/goldens/create_page_settings_dropdown_min_liquidity_tooltip.png
index 6c29457..56704c3 100644
Binary files a/test/app/create/widgets/goldens/create_page_settings_dropdown_min_liquidity_tooltip.png and b/test/app/create/widgets/goldens/create_page_settings_dropdown_min_liquidity_tooltip.png differ
diff --git a/test/app/create/widgets/goldens/create_page_settings_dropdown_min_liquidity_warning_field.png b/test/app/create/widgets/goldens/create_page_settings_dropdown_min_liquidity_warning_field.png
index 3e24f47..083d8ad 100644
Binary files a/test/app/create/widgets/goldens/create_page_settings_dropdown_min_liquidity_warning_field.png and b/test/app/create/widgets/goldens/create_page_settings_dropdown_min_liquidity_warning_field.png differ
diff --git a/test/app/create/widgets/goldens/create_page_settings_dropdown_pool_types_tooltip_hover.png b/test/app/create/widgets/goldens/create_page_settings_dropdown_pool_types_tooltip_hover.png
index 93348f0..6d1fa3c 100644
Binary files a/test/app/create/widgets/goldens/create_page_settings_dropdown_pool_types_tooltip_hover.png and b/test/app/create/widgets/goldens/create_page_settings_dropdown_pool_types_tooltip_hover.png differ
diff --git a/test/app/create/widgets/goldens/create_page_settings_dropdown_v3_pool_type_disabled.png b/test/app/create/widgets/goldens/create_page_settings_dropdown_v3_pool_type_disabled.png
index 0cc6b41..206b51f 100644
Binary files a/test/app/create/widgets/goldens/create_page_settings_dropdown_v3_pool_type_disabled.png and b/test/app/create/widgets/goldens/create_page_settings_dropdown_v3_pool_type_disabled.png differ
diff --git a/test/app/create/widgets/goldens/create_page_settings_dropdown_v3_pool_type_enable.png b/test/app/create/widgets/goldens/create_page_settings_dropdown_v3_pool_type_enable.png
index 30c2dd9..a083488 100644
Binary files a/test/app/create/widgets/goldens/create_page_settings_dropdown_v3_pool_type_enable.png and b/test/app/create/widgets/goldens/create_page_settings_dropdown_v3_pool_type_enable.png differ
diff --git a/test/app/create/widgets/goldens/create_page_settings_dropdown_v4_pool_type_disabled.png b/test/app/create/widgets/goldens/create_page_settings_dropdown_v4_pool_type_disabled.png
index edcc71b..159c56a 100644
Binary files a/test/app/create/widgets/goldens/create_page_settings_dropdown_v4_pool_type_disabled.png and b/test/app/create/widgets/goldens/create_page_settings_dropdown_v4_pool_type_disabled.png differ
diff --git a/test/app/create/widgets/goldens/create_page_settings_dropdown_v4_pool_type_enable.png b/test/app/create/widgets/goldens/create_page_settings_dropdown_v4_pool_type_enable.png
index 370abc4..ac2d228 100644
Binary files a/test/app/create/widgets/goldens/create_page_settings_dropdown_v4_pool_type_enable.png and b/test/app/create/widgets/goldens/create_page_settings_dropdown_v4_pool_type_enable.png differ
diff --git a/test/core/dtos/yield_dto_test.dart b/test/core/dtos/yield_dto_test.dart
index 473f5de..0b96b7f 100644
--- a/test/core/dtos/yield_dto_test.dart
+++ b/test/core/dtos/yield_dto_test.dart
@@ -1,5 +1,6 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:web3kit/core/ethereum_constants.dart';
+import 'package:zup_app/core/dtos/protocol_dto.dart';
import 'package:zup_app/core/dtos/token_dto.dart';
import 'package:zup_app/core/dtos/yield_dto.dart';
import 'package:zup_app/core/enums/networks.dart';
@@ -85,4 +86,38 @@ void main() {
expect(currentYield.yieldTimeframed(YieldTimeFrame.threeMonth), yield90d);
});
+
+ test("When building the yield dto with default variables, the deployerAddress should be zero address by default", () {
+ expect(
+ YieldDto(
+ token0: TokenDto.fixture(),
+ token1: TokenDto.fixture(),
+ poolAddress: "0x1",
+ chainId: AppNetworks.sepolia.chainId,
+ positionManagerAddress: "0x2",
+ tickSpacing: 1,
+ protocol: ProtocolDto.fixture(),
+ initialFeeTier: 0,
+ currentFeeTier: 0,
+ ).deployerAddress,
+ EthereumConstants.zeroAddress,
+ );
+ });
+
+ test("When building the yield dto with default variables, the hooks should be zero address by default", () {
+ expect(
+ YieldDto(
+ token0: TokenDto.fixture(),
+ token1: TokenDto.fixture(),
+ poolAddress: "0x1",
+ chainId: AppNetworks.sepolia.chainId,
+ positionManagerAddress: "0x2",
+ tickSpacing: 1,
+ protocol: ProtocolDto.fixture(),
+ initialFeeTier: 0,
+ currentFeeTier: 0,
+ ).v4Hooks,
+ EthereumConstants.zeroAddress,
+ );
+ });
}
diff --git a/test/core/enums/goldens/hyperEVM_network_icon.png b/test/core/enums/goldens/hyperEVM_network_icon.png
new file mode 100644
index 0000000..f6614bd
Binary files /dev/null and b/test/core/enums/goldens/hyperEVM_network_icon.png differ
diff --git a/test/core/enums/networks_test.dart b/test/core/enums/networks_test.dart
index 1e77904..968848e 100644
--- a/test/core/enums/networks_test.dart
+++ b/test/core/enums/networks_test.dart
@@ -1,3 +1,4 @@
+import 'package:flutter/src/widgets/basic.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:golden_toolkit/golden_toolkit.dart';
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
@@ -21,7 +22,8 @@ void main() {
expect(AppNetworks.fromValue("mainnet"), AppNetworks.mainnet, reason: "Mainnet should match");
expect(AppNetworks.fromValue("scroll"), AppNetworks.scroll, reason: "Scroll should match");
expect(AppNetworks.fromValue("allNetworks"), AppNetworks.allNetworks, reason: "All networks should match");
- // expect(AppNetworks.fromValue("base"), AppNetworks.base, reason: "Base should match");
+ expect(AppNetworks.fromValue("base"), AppNetworks.base, reason: "Base should match");
+ expect(AppNetworks.fromValue("hyperEvm"), AppNetworks.hyperEvm, reason: "HyperEVM should match");
expect(AppNetworks.fromValue("unichain"), AppNetworks.unichain, reason: "Unichain should match");
// expect(AppNetworks.fromValue("bnb"), AppNetworks.bnb, reason: "BNB should match");
});
@@ -31,7 +33,8 @@ void main() {
expect(AppNetworks.mainnet.label, "Ethereum", reason: "Ethereum Label should match");
expect(AppNetworks.scroll.label, "Scroll", reason: "Scroll Label should match");
expect(AppNetworks.allNetworks.label, "All Networks", reason: "All Networks Label should match");
- // expect(AppNetworks.base.label, "Base", reason: "Base Label should match");
+ expect(AppNetworks.base.label, "Base", reason: "Base Label should match");
+ expect(AppNetworks.hyperEvm.label, "HyperEVM", reason: "HyperEVM Label should match");
expect(AppNetworks.unichain.label, "Unichain", reason: "Unichain Label should match");
// expect(AppNetworks.bnb.label, "BNB Chain", reason: "BNB Chain Label should match");
});
@@ -47,7 +50,8 @@ void main() {
AppNetworks.allNetworks,
AppNetworks.mainnet,
AppNetworks.scroll,
- // AppNetworks.base,
+ AppNetworks.base,
+ AppNetworks.hyperEvm,
AppNetworks.unichain,
// AppNetworks.bnb
]),
@@ -67,7 +71,11 @@ void main() {
});
test("`isTestnet` method should return false for base", () {
- // expect(AppNetworks.base.isTestnet, false);
+ expect(AppNetworks.base.isTestnet, false);
+ });
+
+ test("`isTestnet` method should return false for hyperEVM", () {
+ expect(AppNetworks.hyperEvm.isTestnet, false);
});
test("`isTestnet` method should return false for unichain", () {
@@ -114,17 +122,17 @@ void main() {
reason: "Scroll ChainInfo should match",
);
- // expect(
- // AppNetworks.base.chainInfo,
- // ChainInfo(
- // hexChainId: "0x2105",
- // chainName: "Base",
- // blockExplorerUrls: const ["https://basescan.org"],
- // nativeCurrency: NativeCurrencies.eth.currencyInfo,
- // rpcUrls: const ["https://base-rpc.publicnode.com"],
- // ),
- // reason: "Base ChainInfo should match",
- // );
+ expect(
+ AppNetworks.base.chainInfo,
+ ChainInfo(
+ hexChainId: "0x2105",
+ chainName: "Base",
+ blockExplorerUrls: const ["https://basescan.org"],
+ nativeCurrency: NativeCurrencies.eth.currencyInfo,
+ rpcUrls: const ["https://base-rpc.publicnode.com"],
+ ),
+ reason: "Base ChainInfo should match",
+ );
expect(
AppNetworks.unichain.chainInfo,
@@ -138,6 +146,18 @@ void main() {
reason: "Unichain ChainInfo should match",
);
+ expect(
+ AppNetworks.hyperEvm.chainInfo,
+ ChainInfo(
+ hexChainId: "0x3e7",
+ chainName: "HyperEVM",
+ blockExplorerUrls: const ["https://hyperevmscan.io"],
+ nativeCurrency: NativeCurrencies.hype.currencyInfo,
+ rpcUrls: const ["https://rpc.hyperliquid.xyz/evm"],
+ ),
+ reason: "HyperEVM ChainInfo should match",
+ );
+
// expect(
// AppNetworks.bnb.chainInfo,
// ChainInfo(
@@ -190,17 +210,9 @@ void main() {
reason: "Sepolia rpc url should match",
);
- expect(
- AppNetworks.mainnet.rpcUrl,
- "https://ethereum-rpc.publicnode.com",
- reason: "Ethereum rpc url should match",
- );
+ expect(AppNetworks.mainnet.rpcUrl, "https://ethereum-rpc.publicnode.com", reason: "Ethereum rpc url should match");
- expect(
- AppNetworks.scroll.rpcUrl,
- "https://scroll-rpc.publicnode.com",
- reason: "Scroll rpc url should match",
- );
+ expect(AppNetworks.scroll.rpcUrl, "https://scroll-rpc.publicnode.com", reason: "Scroll rpc url should match");
// expect(
// AppNetworks.base.rpcUrl,
@@ -208,11 +220,7 @@ void main() {
// reason: "Base rpc url should match",
// );
- expect(
- AppNetworks.unichain.rpcUrl,
- "https://unichain-rpc.publicnode.com",
- reason: "Unichain rpc url should match",
- );
+ expect(AppNetworks.unichain.rpcUrl, "https://unichain-rpc.publicnode.com", reason: "Unichain rpc url should match");
// expect(
// AppNetworks.bnb.rpcUrl,
@@ -267,38 +275,32 @@ void main() {
});
zGoldenTest("Sepolia network icon should match", goldenFileName: "sepolia_network_icon", (tester) async {
- await tester.pumpDeviceBuilder(await goldenDeviceBuilder(
- AppNetworks.sepolia.icon,
- device: GoldenDevice.square,
- ));
+ await tester.pumpDeviceBuilder(await goldenDeviceBuilder(AppNetworks.sepolia.icon, device: GoldenDevice.square));
+ });
+
+ zGoldenTest("hyperEVM network icon should match", goldenFileName: "hyperEVM_network_icon", (tester) async {
+ await tester.pumpDeviceBuilder(
+ await goldenDeviceBuilder(
+ SizedBox(height: 100, child: Center(child: AppNetworks.hyperEvm.icon)),
+ device: GoldenDevice.square,
+ ),
+ );
});
zGoldenTest("Ethereum network icon should match", goldenFileName: "ethereum_network_icon", (tester) async {
- await tester.pumpDeviceBuilder(await goldenDeviceBuilder(
- AppNetworks.mainnet.icon,
- device: GoldenDevice.square,
- ));
+ await tester.pumpDeviceBuilder(await goldenDeviceBuilder(AppNetworks.mainnet.icon, device: GoldenDevice.square));
});
- // zGoldenTest("Base network icon should match", goldenFileName: "base_network_icon", (tester) async {
- // await tester.pumpDeviceBuilder(await goldenDeviceBuilder(
- // AppNetworks.base.icon,
- // device: GoldenDevice.square,
- // ));
- // });
+ zGoldenTest("Base network icon should match", goldenFileName: "base_network_icon", (tester) async {
+ await tester.pumpDeviceBuilder(await goldenDeviceBuilder(AppNetworks.base.icon, device: GoldenDevice.square));
+ });
zGoldenTest("Scroll network icon should match", goldenFileName: "scroll_network_icon", (tester) async {
- await tester.pumpDeviceBuilder(await goldenDeviceBuilder(
- AppNetworks.scroll.icon,
- device: GoldenDevice.square,
- ));
+ await tester.pumpDeviceBuilder(await goldenDeviceBuilder(AppNetworks.scroll.icon, device: GoldenDevice.square));
});
zGoldenTest("Unichain network icon should match", goldenFileName: "unichain_network_icon", (tester) async {
- await tester.pumpDeviceBuilder(await goldenDeviceBuilder(
- AppNetworks.unichain.icon,
- device: GoldenDevice.square,
- ));
+ await tester.pumpDeviceBuilder(await goldenDeviceBuilder(AppNetworks.unichain.icon, device: GoldenDevice.square));
});
// zGoldenTest("BNB network icon should match", goldenFileName: "bnb_network_icon", (tester) async {
diff --git a/test/core/enums/protocol_id_test.dart b/test/core/enums/protocol_id_test.dart
index b2d22a2..5a02bd8 100644
--- a/test/core/enums/protocol_id_test.dart
+++ b/test/core/enums/protocol_id_test.dart
@@ -9,6 +9,27 @@ void main() {
},
);
+ test(
+ "when calling 'isAerodromeOrVelodromeSlipstream' and the protocol is indeed aerodromeSlipstream, it should return true",
+ () {
+ expect(ProtocolId.aerodromeSlipstream.isAerodromeOrVelodromeSlipstream, true);
+ },
+ );
+
+ test(
+ "when calling 'isAerodromeOrVelodromeSlipstream' and the protocol is indeed velodromeSlipstream, it should return true",
+ () {
+ expect(ProtocolId.velodromeSlipstream.isAerodromeOrVelodromeSlipstream, true);
+ },
+ );
+
+ test(
+ "when calling 'isAerodromeOrVelodromeSlipstream' and the protocol is not aerodromeSlipstream or velodromeSlipstream, it should return false",
+ () {
+ expect(ProtocolId.unknown.isAerodromeOrVelodromeSlipstream, false);
+ },
+ );
+
test(
"When calling `isPancakeSwapInfinityCL` and the protocol is not pancakeSwapInfinityCL, it should return false",
() {
diff --git a/test/core/pool_service_test.dart b/test/core/pool_service_test.dart
index 91bf353..22d136c 100644
--- a/test/core/pool_service_test.dart
+++ b/test/core/pool_service_test.dart
@@ -4,7 +4,12 @@ import 'package:mocktail/mocktail.dart';
import 'package:web3kit/core/dtos/transaction_receipt.dart';
import 'package:web3kit/core/dtos/transaction_response.dart';
import 'package:web3kit/web3kit.dart';
+import 'package:zup_app/abis/aerodrome_v3_pool.abi.g.dart';
+import 'package:zup_app/abis/aerodrome_v3_position_manager.abi.g.dart';
+import 'package:zup_app/abis/algebra/v1.2.1/pool.abi.g.dart' as algebra_1_2_1_pool;
+import 'package:zup_app/abis/algebra/v1.2.1/position_manager.abi.g.dart' as algebra_1_2_1_position_manager;
import 'package:zup_app/abis/pancake_swap_infinity_cl_pool_manager.abi.g.dart';
+import 'package:zup_app/abis/pancake_swap_infinity_cl_position_manager.abi.g.dart';
import 'package:zup_app/abis/uniswap_v3_pool.abi.g.dart';
import 'package:zup_app/abis/uniswap_v3_position_manager.abi.g.dart';
import 'package:zup_app/abis/uniswap_v4_position_manager.abi.g.dart';
@@ -19,6 +24,7 @@ import 'package:zup_app/core/mixins/v4_pool_liquidity_calculations_mixin.dart';
import 'package:zup_app/core/pool_service.dart';
import 'package:zup_app/core/v4_pool_constants.dart';
+import '../matchers.dart';
import '../mocks.dart';
class _V4PoolLiquidityCalculationsMixinWrapper with V4PoolLiquidityCalculationsMixin {}
@@ -33,13 +39,23 @@ void main() {
late Signer signer;
late YieldDto currentYield;
late TransactionResponse transactionResponse;
+ late AerodromeV3PositionManager aerodromePositionManagerV3;
+ late AerodromeV3Pool aerodromeV3Pool;
+ late algebra_1_2_1_position_manager.PositionManager algebra121PositionManager;
+ late algebra_1_2_1_pool.Pool algebra121Pool;
+ late PancakeSwapInfinityClPositionManager pancakeSwapInfinityCLPositionManager;
- late UniswapV4StateViewImpl stateViewImpl;
+ late UniswapV4StateViewImpl uniswapV4StateViewImpl;
late UniswapV3PoolImpl uniswapV3PoolImpl;
late UniswapV3PositionManagerImpl positionManagerV3Impl;
- late UniswapV4PositionManagerImpl positionManagerV4Impl;
+ late UniswapV4PositionManagerImpl uniswapPositionManagerV4Impl;
late PancakeSwapInfinityClPoolManagerImpl pancakeSwapInfinityCLPoolManagerImpl;
late EthereumAbiCoder ethereumAbiCoder;
+ late AerodromeV3PositionManagerImpl aerodromePositionManagerV3Impl;
+ late algebra_1_2_1_position_manager.PositionManagerImpl algebra121PositionManagerImpl;
+ late algebra_1_2_1_pool.PoolImpl algebra121PoolImpl;
+ late AerodromeV3PoolImpl aerodromeV3PoolImpl;
+ late PancakeSwapInfinityClPositionManagerImpl pancakeSwapInfinityCLPositionManagerImpl;
setUp(() {
registerFallbackValue((
@@ -66,13 +82,22 @@ void main() {
pancakeSwapInfinityCLPoolManager = PancakeSwapInfinityCLPoolManagerMock();
ethereumAbiCoder = EthereumAbiCoderMock();
signer = SignerMock();
+ aerodromePositionManagerV3 = AerodromeV3PositionManagerMock();
+ algebra121PositionManager = Algebra121PositionManagerMock();
+ algebra121Pool = Algebra121PoolMock();
+ aerodromeV3Pool = AerodromeV3PoolMock();
+ pancakeSwapInfinityCLPositionManager = PancakeSwapInfinityCLPositionManagerMock();
pancakeSwapInfinityCLPoolManagerImpl = PancakeSwapInfinityCLPoolManagerImplMock();
-
- stateViewImpl = UniswapV4StateViewImplMock();
+ uniswapV4StateViewImpl = UniswapV4StateViewImplMock();
uniswapV3PoolImpl = UniswapV3PoolImplMock();
positionManagerV3Impl = UniswapV3PositionManagerImplMock();
- positionManagerV4Impl = UniswapV4PositionManagerImplMock();
+ uniswapPositionManagerV4Impl = UniswapV4PositionManagerImplMock();
+ aerodromePositionManagerV3Impl = AerodromeV3PositionManagerImplMock();
+ algebra121PositionManagerImpl = Algebra121PositionManagerImplMock();
+ algebra121PoolImpl = Algebra121PoolImplMock();
+ aerodromeV3PoolImpl = AerodromeV3PoolImplMock();
+ pancakeSwapInfinityCLPositionManagerImpl = PancakeSwapInfinityCLPositionManagerImplMock();
currentYield = YieldDto.fixture();
@@ -83,89 +108,142 @@ void main() {
positionManagerV4,
ethereumAbiCoder,
pancakeSwapInfinityCLPoolManager,
+ pancakeSwapInfinityCLPositionManager,
+ aerodromePositionManagerV3,
+ aerodromeV3Pool,
+ algebra121Pool,
+ algebra121PositionManager,
);
- when(() => uniswapV3Pool.fromRpcProvider(
- contractAddress: any(named: "contractAddress"),
- rpcUrl: any(named: "rpcUrl"),
- )).thenReturn(uniswapV3PoolImpl);
+ when(
+ () => uniswapV3Pool.fromRpcProvider(
+ contractAddress: any(named: "contractAddress"),
+ rpcUrl: any(named: "rpcUrl"),
+ ),
+ ).thenReturn(uniswapV3PoolImpl);
+
+ when(
+ () => positionManagerV3.fromRpcProvider(
+ contractAddress: any(named: "contractAddress"),
+ rpcUrl: any(named: "rpcUrl"),
+ ),
+ ).thenReturn(positionManagerV3Impl);
+
+ when(
+ () => positionManagerV3.fromSigner(
+ contractAddress: any(named: "contractAddress"),
+ signer: any(named: "signer"),
+ ),
+ ).thenReturn(positionManagerV3Impl);
+
+ when(
+ () => positionManagerV4.fromSigner(
+ contractAddress: any(named: "contractAddress"),
+ signer: any(named: "signer"),
+ ),
+ ).thenReturn(uniswapPositionManagerV4Impl);
+
+ when(
+ () => stateView.fromRpcProvider(
+ contractAddress: any(named: "contractAddress"),
+ rpcUrl: any(named: "rpcUrl"),
+ ),
+ ).thenReturn(uniswapV4StateViewImpl);
- when(() => positionManagerV3.fromRpcProvider(
+ when(
+ () => positionManagerV4.fromRpcProvider(
contractAddress: any(named: "contractAddress"),
- rpcUrl: any(named: "rpcUrl"))).thenReturn(positionManagerV3Impl);
+ rpcUrl: any(named: "rpcUrl"),
+ ),
+ ).thenReturn(uniswapPositionManagerV4Impl);
+
+ when(() => uniswapV3PoolImpl.slot0()).thenAnswer(
+ (_) async => (
+ feeProtocol: BigInt.from(0),
+ observationCardinality: BigInt.from(0),
+ observationCardinalityNext: BigInt.from(0),
+ observationIndex: BigInt.from(0),
+ sqrtPriceX96: BigInt.from(0),
+ tick: BigInt.from(0),
+ unlocked: true,
+ ),
+ );
- when(() =>
- positionManagerV3.fromSigner(contractAddress: any(named: "contractAddress"), signer: any(named: "signer")))
- .thenReturn(positionManagerV3Impl);
+ when(
+ () => pancakeSwapInfinityCLPoolManager.fromRpcProvider(
+ contractAddress: any(named: "contractAddress"),
+ rpcUrl: any(named: "rpcUrl"),
+ ),
+ ).thenReturn(pancakeSwapInfinityCLPoolManagerImpl);
- when(() =>
- positionManagerV4.fromSigner(contractAddress: any(named: "contractAddress"), signer: any(named: "signer")))
- .thenReturn(positionManagerV4Impl);
+ when(
+ () => pancakeSwapInfinityCLPoolManager.fromSigner(
+ contractAddress: any(named: "contractAddress"),
+ signer: any(named: "signer"),
+ ),
+ ).thenReturn(pancakeSwapInfinityCLPoolManagerImpl);
- when(() => stateView.fromRpcProvider(contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl")))
- .thenReturn(stateViewImpl);
+ when(
+ () => pancakeSwapInfinityCLPositionManager.fromSigner(
+ contractAddress: any(named: "contractAddress"),
+ signer: any(named: "signer"),
+ ),
+ ).thenReturn(pancakeSwapInfinityCLPositionManagerImpl);
- when(() => positionManagerV4.fromRpcProvider(
+ when(
+ () => pancakeSwapInfinityCLPositionManager.fromRpcProvider(
contractAddress: any(named: "contractAddress"),
- rpcUrl: any(named: "rpcUrl"))).thenReturn(positionManagerV4Impl);
+ rpcUrl: any(named: "rpcUrl"),
+ ),
+ ).thenReturn(pancakeSwapInfinityCLPositionManagerImpl);
when(() => signer.address).thenAnswer((_) async => "0xS0M3_4ddr355");
when(() => transactionResponse.waitConfirmation()).thenAnswer((_) async => TransactionReceipt(hash: "0x123"));
when(() => transactionResponse.hash).thenReturn("0x123");
- when(() => stateViewImpl.getSlot0(poolId: any(named: "poolId"))).thenAnswer((_) async => (
- lpFee: BigInt.from(0),
- protocolFee: BigInt.from(0),
- sqrtPriceX96: BigInt.from(0),
- tick: BigInt.from(0),
- ));
+ when(() => uniswapV4StateViewImpl.getSlot0(poolId: any(named: "poolId"))).thenAnswer(
+ (_) async =>
+ (lpFee: BigInt.from(0), protocolFee: BigInt.from(0), sqrtPriceX96: BigInt.from(0), tick: BigInt.from(0)),
+ );
});
- test(
- "When calling `getPoolTick` and the pool is v4, it should use the state view contract to get it",
- () async {
- final expectedTick = BigInt.from(87654);
- when(() => stateViewImpl.getSlot0(poolId: any(named: "poolId"))).thenAnswer((_) async => (
- lpFee: BigInt.from(0),
- protocolFee: BigInt.from(0),
- sqrtPriceX96: BigInt.from(0),
- tick: expectedTick,
- ));
- when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer((_) async => (
- lpFee: BigInt.from(0),
- protocolFee: BigInt.from(0),
- sqrtPriceX96: BigInt.from(0),
- tick: expectedTick,
- ));
- final currentYield0 = currentYield.copyWith(poolType: PoolType.v4, v4StateView: "0x123");
- final result = await sut.getPoolTick(currentYield0);
+ test("When calling `getPoolTick` and the pool is v4, it should use the state view contract to get it", () async {
+ final expectedTick = BigInt.from(87654);
+ when(() => uniswapV4StateViewImpl.getSlot0(poolId: any(named: "poolId"))).thenAnswer(
+ (_) async =>
+ (lpFee: BigInt.from(0), protocolFee: BigInt.from(0), sqrtPriceX96: BigInt.from(0), tick: expectedTick),
+ );
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer(
+ (_) async =>
+ (lpFee: BigInt.from(0), protocolFee: BigInt.from(0), sqrtPriceX96: BigInt.from(0), tick: expectedTick),
+ );
+ final currentYield0 = currentYield.copyWith(poolType: PoolType.v4, v4StateView: "0x123");
+ final result = await sut.getPoolTick(currentYield0);
- expect(result, expectedTick);
- verify(() => stateViewImpl.getSlot0(poolId: currentYield0.poolAddress)).called(1);
- },
- );
+ expect(result, expectedTick);
+ verify(() => uniswapV4StateViewImpl.getSlot0(poolId: currentYield0.poolAddress)).called(1);
+ });
- test(
- "When calling `getPoolTick` and the pool is v3, it should use the v3 pool contract to get it",
- () async {
- final expectedTick = BigInt.from(2127);
- when(() => uniswapV3PoolImpl.slot0()).thenAnswer((_) async => (
- feeProtocol: BigInt.from(0),
- observationCardinality: BigInt.from(0),
- observationCardinalityNext: BigInt.from(0),
- observationIndex: BigInt.from(0),
- sqrtPriceX96: BigInt.from(0),
- tick: expectedTick,
- unlocked: true
- ));
+ test("When calling `getPoolTick` and the pool is v3, it should use the v3 pool contract to get it", () async {
+ final expectedTick = BigInt.from(2127);
+ when(() => uniswapV3PoolImpl.slot0()).thenAnswer(
+ (_) async => (
+ feeProtocol: BigInt.from(0),
+ observationCardinality: BigInt.from(0),
+ observationCardinalityNext: BigInt.from(0),
+ observationIndex: BigInt.from(0),
+ sqrtPriceX96: BigInt.from(0),
+ tick: expectedTick,
+ unlocked: true,
+ ),
+ );
- final currentYield0 = currentYield.copyWith(poolType: PoolType.v3);
- final result = await sut.getPoolTick(currentYield0);
+ final currentYield0 = currentYield.copyWith(poolType: PoolType.v3);
+ final result = await sut.getPoolTick(currentYield0);
- expect(result, expectedTick);
- verify(() => uniswapV3PoolImpl.slot0()).called(1);
- },
- );
+ expect(result, expectedTick);
+ verify(() => uniswapV3PoolImpl.slot0()).called(1);
+ });
test(
"""when calling `sendV3PoolDepositTransaction` with token0 native,
@@ -177,21 +255,20 @@ void main() {
const network = AppNetworks.mainnet;
final currentYield0 = currentYield.copyWith(
- poolType: PoolType.v3,
- chainId: network.chainId,
- token0: TokenDto.fixture().copyWith(addresses: {
- network.chainId: EthereumConstants.zeroAddress,
- }),
- token1: TokenDto.fixture().copyWith(addresses: {
- network.chainId: "0x123",
- }));
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: EthereumConstants.zeroAddress}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x123"}),
+ );
when(() => positionManagerV3.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
when(() => positionManagerV3.getRefundETHCalldata()).thenReturn(refundCalldata);
- when(() => positionManagerV3Impl.multicall(data: any(named: "data"), ethValue: any(named: "ethValue")))
- .thenAnswer(
- (_) async => transactionResponse,
- );
+ when(
+ () => positionManagerV3Impl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
final amount0Desired = BigInt.from(100);
final amount1Desired = BigInt.from(100);
@@ -236,17 +313,20 @@ void main() {
const network = AppNetworks.mainnet;
final currentYield0 = currentYield.copyWith(
- poolType: PoolType.v3,
- chainId: network.chainId,
- token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
- token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}));
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
when(() => positionManagerV3.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
when(() => positionManagerV3.getRefundETHCalldata()).thenReturn(refundCalldata);
- when(() => positionManagerV3Impl.multicall(data: any(named: "data"), ethValue: any(named: "ethValue")))
- .thenAnswer(
- (_) async => transactionResponse,
- );
+ when(
+ () => positionManagerV3Impl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
final amount0Desired = BigInt.from(4311);
final amount1Desired = BigInt.from(1031900);
@@ -271,19 +351,21 @@ void main() {
);
verify(
- () => positionManagerV3.getMintCalldata(params: (
- amount0Desired: amount0Desired,
- amount0Min: amount0Min,
- amount1Desired: amount1Desired,
- amount1Min: amount1Min,
- deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
- fee: BigInt.from(currentYield0.feeTier),
- recipient: recipient,
- tickLower: tickLower,
- tickUpper: tickUpper,
- token0: network.wrappedNativeTokenAddress,
- token1: token1Address,
- )),
+ () => positionManagerV3.getMintCalldata(
+ params: (
+ amount0Desired: amount0Desired,
+ amount0Min: amount0Min,
+ amount1Desired: amount1Desired,
+ amount1Min: amount1Min,
+ deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
+ fee: BigInt.from(currentYield0.initialFeeTier),
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ token0: network.wrappedNativeTokenAddress,
+ token1: token1Address,
+ ),
+ ),
).called(1);
});
},
@@ -301,17 +383,20 @@ void main() {
const network = AppNetworks.mainnet;
final currentYield0 = currentYield.copyWith(
- poolType: PoolType.v3,
- chainId: network.chainId,
- token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
- token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}));
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
when(() => positionManagerV3.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
when(() => positionManagerV3.getRefundETHCalldata()).thenReturn(refundCalldata);
- when(() => positionManagerV3Impl.multicall(data: any(named: "data"), ethValue: any(named: "ethValue")))
- .thenAnswer(
- (_) async => transactionResponse,
- );
+ when(
+ () => positionManagerV3Impl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
final amount0Desired = BigInt.from(100);
final amount1Desired = BigInt.from(31);
@@ -336,19 +421,21 @@ void main() {
);
verify(
- () => positionManagerV3.getMintCalldata(params: (
- amount0Desired: amount0Desired,
- amount0Min: amount0Min,
- amount1Desired: amount1Desired,
- amount1Min: amount1Min,
- deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
- fee: BigInt.from(currentYield0.feeTier),
- recipient: recipient,
- tickLower: tickLower,
- tickUpper: tickUpper,
- token0: token0Address,
- token1: network.wrappedNativeTokenAddress,
- )),
+ () => positionManagerV3.getMintCalldata(
+ params: (
+ amount0Desired: amount0Desired,
+ amount0Min: amount0Min,
+ amount1Desired: amount1Desired,
+ amount1Min: amount1Min,
+ deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
+ fee: BigInt.from(currentYield0.initialFeeTier),
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ token0: token0Address,
+ token1: network.wrappedNativeTokenAddress,
+ ),
+ ),
).called(1);
});
},
@@ -366,17 +453,20 @@ void main() {
const network = AppNetworks.mainnet;
final currentYield0 = currentYield.copyWith(
- poolType: PoolType.v3,
- chainId: network.chainId,
- token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
- token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}));
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
when(() => positionManagerV3.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
when(() => positionManagerV3.getRefundETHCalldata()).thenReturn(refundCalldata);
- when(() => positionManagerV3Impl.multicall(data: any(named: "data"), ethValue: any(named: "ethValue")))
- .thenAnswer(
- (_) async => transactionResponse,
- );
+ when(
+ () => positionManagerV3Impl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
final amount0Desired = BigInt.from(4311);
final amount1Desired = BigInt.from(1031900);
@@ -401,7 +491,10 @@ void main() {
);
verify(
- () => positionManagerV3Impl.multicall(ethValue: amount0Desired, data: any(named: "data")),
+ () => positionManagerV3Impl.multicall(
+ ethValue: amount0Desired,
+ data: any(named: "data"),
+ ),
).called(1);
});
},
@@ -419,17 +512,20 @@ void main() {
const network = AppNetworks.mainnet;
final currentYield0 = currentYield.copyWith(
- poolType: PoolType.v3,
- chainId: network.chainId,
- token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
- token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}));
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
when(() => positionManagerV3.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
when(() => positionManagerV3.getRefundETHCalldata()).thenReturn(refundCalldata);
- when(() => positionManagerV3Impl.multicall(data: any(named: "data"), ethValue: any(named: "ethValue")))
- .thenAnswer(
- (_) async => transactionResponse,
- );
+ when(
+ () => positionManagerV3Impl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
final amount0Desired = BigInt.from(4311);
final amount1Desired = BigInt.from(1031900);
@@ -454,7 +550,10 @@ void main() {
);
verify(
- () => positionManagerV3Impl.multicall(ethValue: amount1Desired, data: any(named: "data")),
+ () => positionManagerV3Impl.multicall(
+ ethValue: amount1Desired,
+ data: any(named: "data"),
+ ),
).called(1);
});
},
@@ -468,18 +567,21 @@ void main() {
const token1Address = "0x315768";
const token0Address = "0x20172891";
- when(() => positionManagerV3Impl.mint(params: any(named: "params"), ethValue: any(named: "ethValue")))
- .thenAnswer(
- (_) async => transactionResponse,
- );
+ when(
+ () => positionManagerV3Impl.mint(
+ params: any(named: "params"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
const network = AppNetworks.mainnet;
final currentYield0 = currentYield.copyWith(
- feeTier: 3982,
- poolType: PoolType.v3,
- chainId: network.chainId,
- token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
- token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}));
+ initialFeeTier: 3982,
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
final amount0Desired = BigInt.from(4311);
final amount1Desired = BigInt.from(1031900);
@@ -508,7 +610,7 @@ void main() {
params: (
token0: token0Address,
token1: token1Address,
- fee: BigInt.from(currentYield0.feeTier),
+ fee: BigInt.from(currentYield0.initialFeeTier),
tickLower: tickLower,
tickUpper: tickUpper,
amount0Desired: amount0Desired,
@@ -526,119 +628,175 @@ void main() {
);
test(
- "When calling `sendV4PoolDepositTransaction` and the token0 is native, it should encode packed the correct actions including the sweep",
- () async {
- when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
- when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
- when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
- ).thenAnswer((_) async => transactionResponse);
+ "When calling `sendV4PoolDepositTransaction` and the token0 is native, it should encode packed the correct actions including the sweep",
+ () async {
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+ when(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
- const network = AppNetworks.mainnet;
- final amount0Desired = BigInt.from(4311);
- final amount1Desired = BigInt.from(1031900);
- const deadline = Duration(days: 1);
- final amount0Max = BigInt.from(4312);
- final amount1Max = BigInt.from(1031901);
- final recipient = await signer.address;
- final tickLower = BigInt.from(321);
- final tickUpper = BigInt.from(1222);
+ const network = AppNetworks.mainnet;
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Max = BigInt.from(4312);
+ final amount1Max = BigInt.from(1031901);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
- final currentYield0 = currentYield.copyWith(
- chainId: network.chainId,
- poolType: PoolType.v4,
- v4StateView: "0x1",
- token0: TokenDto.fixture().copyWith(addresses: {network.chainId: EthereumConstants.zeroAddress}),
- token1: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x1"}),
- );
+ final currentYield0 = currentYield.copyWith(
+ chainId: network.chainId,
+ poolType: PoolType.v4,
+ v4StateView: "0x1",
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: EthereumConstants.zeroAddress}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x1"}),
+ );
- await sut.sendV4PoolDepositTransaction(
- currentYield0,
- signer,
- deadline: deadline,
- tickLower: tickLower,
- tickUpper: tickUpper,
- amount0toDeposit: amount0Desired,
- amount1ToDeposit: amount1Desired,
- maxAmount0ToDeposit: amount0Max,
- maxAmount1ToDeposit: amount1Max,
- recipient: recipient,
- );
+ await sut.sendV4PoolDepositTransaction(
+ currentYield0,
+ signer,
+ deadline: deadline,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ amount0toDeposit: amount0Desired,
+ amount1ToDeposit: amount1Desired,
+ maxAmount0ToDeposit: amount0Max,
+ maxAmount1ToDeposit: amount1Max,
+ recipient: recipient,
+ );
- verify(() => ethereumAbiCoder.encodePacked([
- "uint8",
- "uint8",
- "uint8"
- ], [
- V4PoolConstants.mintPositionActionValue,
- V4PoolConstants.settlePairActionValue,
- V4PoolConstants.sweepActionValue
- ])).called(1);
- });
+ verify(
+ () => ethereumAbiCoder.encodePacked(
+ ["uint8", "uint8", "uint8"],
+ [
+ V4PoolConstants.mintPositionActionValue,
+ V4PoolConstants.uniswapSettlePairActionValue,
+ V4PoolConstants.uniswapSweepActionValue,
+ ],
+ ),
+ ).called(1);
+ },
+ );
test(
- "When calling `sendV4PoolDepositTransaction` and the token1 is native, it should encode packed the correct actions including the sweep",
- () async {
- when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
- when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
- when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
- ).thenAnswer((_) async => transactionResponse);
-
- const network = AppNetworks.mainnet;
- final amount0Desired = BigInt.from(4311);
- final amount1Desired = BigInt.from(1031900);
- const deadline = Duration(days: 1);
- final amount0Max = BigInt.from(4312);
- final amount1Max = BigInt.from(1031901);
- final recipient = await signer.address;
- final tickLower = BigInt.from(321);
- final tickUpper = BigInt.from(1222);
+ "When calling `sendV4PoolDepositTransaction` and the token1 is native, it should encode packed the correct actions including the sweep",
+ () async {
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+ when(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
- final currentYield0 = currentYield.copyWith(
- chainId: network.chainId,
- v4StateView: "0x1",
- poolType: PoolType.v4,
- token1: TokenDto.fixture().copyWith(addresses: {network.chainId: EthereumConstants.zeroAddress}),
- token0: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x1"}),
- );
+ const network = AppNetworks.mainnet;
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Max = BigInt.from(4312);
+ final amount1Max = BigInt.from(1031901);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
- await sut.sendV4PoolDepositTransaction(
- currentYield0,
- signer,
- deadline: deadline,
- tickLower: tickLower,
- tickUpper: tickUpper,
- amount0toDeposit: amount0Desired,
- amount1ToDeposit: amount1Desired,
- maxAmount0ToDeposit: amount0Max,
- maxAmount1ToDeposit: amount1Max,
- recipient: recipient,
- );
+ final currentYield0 = currentYield.copyWith(
+ chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: EthereumConstants.zeroAddress}),
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x1"}),
+ );
- verify(() => ethereumAbiCoder.encodePacked([
- "uint8",
- "uint8",
- "uint8"
- ], [
- V4PoolConstants.mintPositionActionValue,
- V4PoolConstants.settlePairActionValue,
- V4PoolConstants.sweepActionValue
- ])).called(1);
- });
+ await sut.sendV4PoolDepositTransaction(
+ currentYield0,
+ signer,
+ deadline: deadline,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ amount0toDeposit: amount0Desired,
+ amount1ToDeposit: amount1Desired,
+ maxAmount0ToDeposit: amount0Max,
+ maxAmount1ToDeposit: amount1Max,
+ recipient: recipient,
+ );
+
+ verify(
+ () => ethereumAbiCoder.encodePacked(
+ ["uint8", "uint8", "uint8"],
+ [
+ V4PoolConstants.mintPositionActionValue,
+ V4PoolConstants.uniswapSettlePairActionValue,
+ V4PoolConstants.uniswapSweepActionValue,
+ ],
+ ),
+ ).called(1);
+ },
+ );
test(
- "When calling `sendV4PoolDepositTransaction` and none of the tokens are native, it should not include the sweep action",
- () async {
- when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
- when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
- when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
- ).thenAnswer((_) async => transactionResponse);
+ "When calling `sendV4PoolDepositTransaction` and none of the tokens are native, it should not include the sweep action",
+ () async {
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+ when(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ const network = AppNetworks.mainnet;
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Max = BigInt.from(4312);
+ final amount1Max = BigInt.from(1031901);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ final currentYield0 = currentYield.copyWith(
+ chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x2"}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x1"}),
+ );
+
+ await sut.sendV4PoolDepositTransaction(
+ currentYield0,
+ signer,
+ deadline: deadline,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ amount0toDeposit: amount0Desired,
+ amount1ToDeposit: amount1Desired,
+ maxAmount0ToDeposit: amount0Max,
+ maxAmount1ToDeposit: amount1Max,
+ recipient: recipient,
+ );
+ verify(
+ () => ethereumAbiCoder.encodePacked(
+ ["uint8", "uint8"],
+ [V4PoolConstants.mintPositionActionValue, V4PoolConstants.uniswapSettlePairActionValue],
+ ),
+ ).called(1);
+ },
+ );
+
+ test("When calling `sendV4PoolDepositTransaction` the mint action params should be correctly encoded", () async {
+ const token0Address = "0x1";
+ const token1Address = "0x2";
const network = AppNetworks.mainnet;
final amount0Desired = BigInt.from(4311);
final amount1Desired = BigInt.from(1031900);
@@ -648,13 +806,29 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
+ final sqrtPriceX96 = BigInt.from(2167212171927187);
+
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+ when(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ when(() => uniswapV4StateViewImpl.getSlot0(poolId: any(named: "poolId"))).thenAnswer(
+ (_) async =>
+ (lpFee: BigInt.from(0), protocolFee: BigInt.from(0), sqrtPriceX96: sqrtPriceX96, tick: BigInt.from(0)),
+ );
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
v4StateView: "0x1",
poolType: PoolType.v4,
- token0: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x2"}),
- token1: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x1"}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
);
await sut.sendV4PoolDepositTransaction(
@@ -670,17 +844,47 @@ void main() {
recipient: recipient,
);
- verify(() => ethereumAbiCoder.encodePacked([
- "uint8",
- "uint8",
- ], [
- V4PoolConstants.mintPositionActionValue,
- V4PoolConstants.settlePairActionValue,
- ])).called(1);
+ verify(
+ () => ethereumAbiCoder.encode(
+ [
+ "tuple(address,address,int32,int24,address)",
+ "int24",
+ "int24",
+ "uint256",
+ "uint128",
+ "uint128",
+ "address",
+ "bytes",
+ ],
+ [
+ [
+ token0Address,
+ token1Address,
+ BigInt.from(currentYield0.initialFeeTier),
+ BigInt.from(currentYield0.tickSpacing),
+ currentYield0.v4Hooks,
+ ],
+ tickLower,
+ tickUpper,
+ _V4PoolLiquidityCalculationsMixinWrapper().getLiquidityForAmounts(
+ sqrtPriceX96,
+ _V4PoolLiquidityCalculationsMixinWrapper().getSqrtPriceAtTick(tickLower),
+ _V4PoolLiquidityCalculationsMixinWrapper().getSqrtPriceAtTick(tickUpper),
+ amount0Desired,
+ amount1Desired,
+ ),
+ amount0Max,
+ amount1Max,
+ recipient,
+ EthereumConstants.emptyBytes,
+ ],
+ ),
+ ).called(1);
});
test(
- "When calling `sendV4PoolDepositTransaction` the mint action params should be correctly encoded",
+ """When calling `sendV4PoolDepositTransaction` and the protocol is Pancake Swap
+ infinity the mint action params should be correctly encoded""",
() async {
const token0Address = "0x1";
const token1Address = "0x2";
@@ -694,25 +898,42 @@ void main() {
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
final sqrtPriceX96 = BigInt.from(2167212171927187);
+ const parameters = "0x2186271217625167f2ffff";
+ const hooks = "0x2111";
+ const poolManager = "0xAAABbbaaa";
when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
+ () => pancakeSwapInfinityCLPositionManagerImpl.modifyLiquidities(
+ payload: any(named: "payload"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
).thenAnswer((_) async => transactionResponse);
- when(() => stateViewImpl.getSlot0(poolId: any(named: "poolId"))).thenAnswer((_) async => (
- lpFee: BigInt.from(0),
- protocolFee: BigInt.from(0),
- sqrtPriceX96: sqrtPriceX96,
- tick: BigInt.from(0),
- ));
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer(
+ (_) async =>
+ (lpFee: BigInt.from(0), protocolFee: BigInt.from(0), sqrtPriceX96: sqrtPriceX96, tick: BigInt.from(0)),
+ );
+
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.poolIdToPoolKey(id: any(named: "id"))).thenAnswer(
+ (_) async => (
+ currency0: token0Address,
+ currency1: token1Address,
+ fee: BigInt.from(21),
+ hooks: hooks,
+ parameters: parameters,
+ poolManager: poolManager,
+ ),
+ );
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
- v4StateView: "0x1",
+ v4PoolManager: poolManager,
+ v4Hooks: hooks,
poolType: PoolType.v4,
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.pancakeSwapInfinityCL),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
);
@@ -730,23 +951,20 @@ void main() {
recipient: recipient,
);
- verify(() => ethereumAbiCoder.encode([
- "tuple(address,address,int32,int24,address)",
+ verify(
+ () => ethereumAbiCoder.encode(
+ [
+ "tuple(address,address,address,address,uint24,bytes32)",
"int24",
"int24",
"uint256",
"uint128",
"uint128",
"address",
- "bytes"
- ], [
- [
- token0Address,
- token1Address,
- BigInt.from(currentYield0.feeTier),
- BigInt.from(currentYield0.tickSpacing),
- currentYield0.v4Hooks,
- ],
+ "bytes",
+ ],
+ [
+ [token0Address, token1Address, hooks, poolManager, currentYield0.initialFeeTier, parameters],
tickLower,
tickUpper,
_V4PoolLiquidityCalculationsMixinWrapper().getLiquidityForAmounts(
@@ -760,20 +978,17 @@ void main() {
amount1Max,
recipient,
EthereumConstants.emptyBytes,
- ])).called(1);
+ ],
+ ),
+ ).called(1);
},
);
test(
- "When calling `sendV4PoolDepositTransaction` the settle pair action params should be correctly encoded",
+ """When calling `sendV4PoolDepositTransaction` and the protocol is Pancake Swap
+ infinity, it should get the pool parameters from the pool manager and
+ encode it correctly in the mint action""",
() async {
- when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
- when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
- when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
- ).thenAnswer((_) async => transactionResponse);
-
const token0Address = "0x1";
const token1Address = "0x2";
const network = AppNetworks.mainnet;
@@ -785,11 +1000,43 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
+ final sqrtPriceX96 = BigInt.from(2167212171927187);
+ const parameters = "0x2186271217625167f2ffff";
+ const hooks = "0x2111";
+ const poolManager = "0xAAABbbaaa";
+
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+ when(
+ () => pancakeSwapInfinityCLPositionManagerImpl.modifyLiquidities(
+ payload: any(named: "payload"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer(
+ (_) async =>
+ (lpFee: BigInt.from(0), protocolFee: BigInt.from(0), sqrtPriceX96: sqrtPriceX96, tick: BigInt.from(0)),
+ );
+
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.poolIdToPoolKey(id: any(named: "id"))).thenAnswer(
+ (_) async => (
+ currency0: token0Address,
+ currency1: token1Address,
+ fee: BigInt.from(21),
+ hooks: hooks,
+ parameters: parameters,
+ poolManager: poolManager,
+ ),
+ );
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
- v4StateView: "0x1",
+ v4PoolManager: poolManager,
+ v4Hooks: hooks,
poolType: PoolType.v4,
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.pancakeSwapInfinityCL),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
);
@@ -807,21 +1054,26 @@ void main() {
recipient: recipient,
);
- verify(() => ethereumAbiCoder.encode(["address", "address"], [token0Address, token1Address])).called(1);
+ verify(
+ () => ethereumAbiCoder.encode([
+ "tuple(address,address,address,address,uint24,bytes32)",
+ "int24",
+ "int24",
+ "uint256",
+ "uint128",
+ "uint128",
+ "address",
+ "bytes",
+ ], any(that: ObjectParamMatcher((object) => object[0].last == parameters))),
+ ).called(1);
},
);
test(
- "When calling `sendV4PoolDepositTransaction` and the token0 is native the sweep action params should be correctly encoded",
+ """When calling `sendV4PoolDepositTransaction` and the protocol is Pancake Swap
+ infinity the actions should be correctly encoded""",
() async {
- when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
- when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
- when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
- ).thenAnswer((_) async => transactionResponse);
-
- const token0Address = EthereumConstants.zeroAddress;
+ const token0Address = "0x1";
const token1Address = "0x2";
const network = AppNetworks.mainnet;
final amount0Desired = BigInt.from(4311);
@@ -832,11 +1084,43 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
+ final sqrtPriceX96 = BigInt.from(2167212171927187);
+ const parameters = "0x2186271217625167f2ffff";
+ const hooks = "0x2111";
+ const poolManager = "0xAAABbbaaa";
+
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+ when(
+ () => pancakeSwapInfinityCLPositionManagerImpl.modifyLiquidities(
+ payload: any(named: "payload"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer(
+ (_) async =>
+ (lpFee: BigInt.from(0), protocolFee: BigInt.from(0), sqrtPriceX96: sqrtPriceX96, tick: BigInt.from(0)),
+ );
+
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.poolIdToPoolKey(id: any(named: "id"))).thenAnswer(
+ (_) async => (
+ currency0: token0Address,
+ currency1: token1Address,
+ fee: BigInt.from(21),
+ hooks: hooks,
+ parameters: parameters,
+ poolManager: poolManager,
+ ),
+ );
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
- v4StateView: "0x1",
+ v4PoolManager: poolManager,
+ v4Hooks: hooks,
poolType: PoolType.v4,
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.pancakeSwapInfinityCL),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
);
@@ -855,26 +1139,24 @@ void main() {
);
verify(
- () => ethereumAbiCoder.encode(
- ["address", "address"],
- [EthereumConstants.zeroAddress, recipient],
+ () => ethereumAbiCoder.encodePacked(
+ ["uint8", "uint8", "uint8"],
+ [
+ V4PoolConstants.mintPositionActionValue,
+ V4PoolConstants.pancakeSwapCloseCurrencyActionValue,
+ V4PoolConstants.pancakeSwapCloseCurrencyActionValue,
+ ],
),
).called(1);
},
);
test(
- "When calling `sendV4PoolDepositTransaction` and the token1 is native the sweep action params should be correctly encoded",
+ """When calling `sendV4PoolDepositTransaction` and the protocol is Pancake Swap
+ infinity the close currency action should be correctly encoded for token1 and token0""",
() async {
- when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
- when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
- when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
- ).thenAnswer((_) async => transactionResponse);
-
- const token0Address = "0x2";
- const token1Address = EthereumConstants.zeroAddress;
+ const token0Address = "0x1";
+ const token1Address = "0x2";
const network = AppNetworks.mainnet;
final amount0Desired = BigInt.from(4311);
final amount1Desired = BigInt.from(1031900);
@@ -884,13 +1166,45 @@ void main() {
final recipient = await signer.address;
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
+ final sqrtPriceX96 = BigInt.from(2167212171927187);
+ const parameters = "0x2186271217625167f2ffff";
+ const hooks = "0x2111";
+ const poolManager = "0xAAABbbaaa";
+
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+ when(
+ () => pancakeSwapInfinityCLPositionManagerImpl.modifyLiquidities(
+ payload: any(named: "payload"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer(
+ (_) async =>
+ (lpFee: BigInt.from(0), protocolFee: BigInt.from(0), sqrtPriceX96: sqrtPriceX96, tick: BigInt.from(0)),
+ );
+
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.poolIdToPoolKey(id: any(named: "id"))).thenAnswer(
+ (_) async => (
+ currency0: token0Address,
+ currency1: token1Address,
+ fee: BigInt.from(21),
+ hooks: hooks,
+ parameters: parameters,
+ poolManager: poolManager,
+ ),
+ );
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
- v4StateView: "0x1",
+ v4PoolManager: poolManager,
+ v4Hooks: hooks,
poolType: PoolType.v4,
- token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.pancakeSwapInfinityCL),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
);
await sut.sendV4PoolDepositTransaction(
@@ -906,26 +1220,25 @@ void main() {
recipient: recipient,
);
- verify(
- () => ethereumAbiCoder.encode(
- ["address", "address"],
- [EthereumConstants.zeroAddress, recipient],
- ),
- ).called(1);
+ verify(() => ethereumAbiCoder.encode(["address"], [token0Address])).called(1);
+ verify(() => ethereumAbiCoder.encode(["address"], [token1Address])).called(1);
},
);
test(
- """When calling `sendV4PoolDepositTransaction` and the token0 is native,
- it should send the correct unlock data to the contract to add liquidity""",
+ "When calling `sendV4PoolDepositTransaction` the settle pair action params should be correctly encoded",
() async {
- const actionsEncoded = "0xhvaaa";
- const mintPositionActionParamsEncoded = "0xaaaa";
- const settlePairActionParamsEncoded = "0xbbbb";
- const sweepActionParamsEncoded = "0xcccc";
- const unlockData = "0xaaaaa77777AAA";
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+ when(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
- const token0Address = EthereumConstants.zeroAddress;
+ const token0Address = "0x1";
const token1Address = "0x2";
const network = AppNetworks.mainnet;
final amount0Desired = BigInt.from(4311);
@@ -941,40 +1254,10 @@ void main() {
chainId: network.chainId,
v4StateView: "0x1",
poolType: PoolType.v4,
- token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
);
- when(() => ethereumAbiCoder.encodePacked(["uint8", "uint8", "uint8"], any())).thenReturn(actionsEncoded);
- when(() => ethereumAbiCoder.encode([
- "tuple(address,address,int32,int24,address)",
- "int24",
- "int24",
- "uint256",
- "uint128",
- "uint128",
- "address",
- "bytes"
- ], any())).thenReturn(mintPositionActionParamsEncoded);
- when(() => ethereumAbiCoder.encode(["address", "address"], [token0Address, token1Address]))
- .thenReturn(settlePairActionParamsEncoded);
-
- when(() => ethereumAbiCoder.encode(["address", "address"], [EthereumConstants.zeroAddress, recipient]))
- .thenReturn(sweepActionParamsEncoded);
-
- when(() => ethereumAbiCoder.encode([
- "bytes",
- "bytes[]"
- ], [
- actionsEncoded,
- [mintPositionActionParamsEncoded, settlePairActionParamsEncoded, sweepActionParamsEncoded]
- ])).thenReturn(unlockData);
-
- when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
- ).thenAnswer((_) async => transactionResponse);
-
await sut.sendV4PoolDepositTransaction(
currentYield0,
signer,
@@ -988,28 +1271,25 @@ void main() {
recipient: recipient,
);
- verify(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: unlockData,
- deadline: any(named: "deadline"),
- ethValue: any(named: "ethValue"),
- ),
- ).called(1);
+ verify(() => ethereumAbiCoder.encode(["address", "address"], [token0Address, token1Address])).called(1);
},
);
test(
- """When calling `sendV4PoolDepositTransaction` and the token1 is native,
- it should send the correct unlock data to the contract to add liquidity""",
+ "When calling `sendV4PoolDepositTransaction` and the token0 is native the sweep action params should be correctly encoded",
() async {
- const actionsEncoded = "0xhvaaa";
- const mintPositionActionParamsEncoded = "0xaaaa";
- const settlePairActionParamsEncoded = "0xbbbb";
- const sweepActionParamsEncoded = "0xcccc";
- const unlockData = "0xaaaaa77777AAA";
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+ when(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
- const token1Address = EthereumConstants.zeroAddress;
- const token0Address = "0x2";
+ const token0Address = EthereumConstants.zeroAddress;
+ const token1Address = "0x2";
const network = AppNetworks.mainnet;
final amount0Desired = BigInt.from(4311);
final amount1Desired = BigInt.from(1031900);
@@ -1024,40 +1304,62 @@ void main() {
chainId: network.chainId,
v4StateView: "0x1",
poolType: PoolType.v4,
- token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
);
- when(() => ethereumAbiCoder.encodePacked(["uint8", "uint8", "uint8"], any())).thenReturn(actionsEncoded);
- when(() => ethereumAbiCoder.encode([
- "tuple(address,address,int32,int24,address)",
- "int24",
- "int24",
- "uint256",
- "uint128",
- "uint128",
- "address",
- "bytes"
- ], any())).thenReturn(mintPositionActionParamsEncoded);
- when(() => ethereumAbiCoder.encode(["address", "address"], [token0Address, token1Address]))
- .thenReturn(settlePairActionParamsEncoded);
-
- when(() => ethereumAbiCoder.encode(["address", "address"], [EthereumConstants.zeroAddress, recipient]))
- .thenReturn(sweepActionParamsEncoded);
+ await sut.sendV4PoolDepositTransaction(
+ currentYield0,
+ signer,
+ deadline: deadline,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ amount0toDeposit: amount0Desired,
+ amount1ToDeposit: amount1Desired,
+ maxAmount0ToDeposit: amount0Max,
+ maxAmount1ToDeposit: amount1Max,
+ recipient: recipient,
+ );
- when(() => ethereumAbiCoder.encode([
- "bytes",
- "bytes[]"
- ], [
- actionsEncoded,
- [mintPositionActionParamsEncoded, settlePairActionParamsEncoded, sweepActionParamsEncoded]
- ])).thenReturn(unlockData);
+ verify(
+ () => ethereumAbiCoder.encode(["address", "address"], [EthereumConstants.zeroAddress, recipient]),
+ ).called(1);
+ },
+ );
+ test(
+ "When calling `sendV4PoolDepositTransaction` and the token1 is native the sweep action params should be correctly encoded",
+ () async {
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
).thenAnswer((_) async => transactionResponse);
+ const token0Address = "0x2";
+ const token1Address = EthereumConstants.zeroAddress;
+ const network = AppNetworks.mainnet;
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Max = BigInt.from(4312);
+ final amount1Max = BigInt.from(1031901);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ final currentYield0 = currentYield.copyWith(
+ chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
await sut.sendV4PoolDepositTransaction(
currentYield0,
signer,
@@ -1072,25 +1374,22 @@ void main() {
);
verify(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: unlockData,
- deadline: any(named: "deadline"),
- ethValue: any(named: "ethValue"),
- ),
+ () => ethereumAbiCoder.encode(["address", "address"], [EthereumConstants.zeroAddress, recipient]),
).called(1);
},
);
test(
- """When calling `sendV4PoolDepositTransaction` and none of the tokens are native,
- it should send the correct unlock data to the contract to add liquidity (without sweep)""",
+ """When calling `sendV4PoolDepositTransaction` and the token0 is native,
+ it should send the correct unlock data to the contract to add liquidity""",
() async {
const actionsEncoded = "0xhvaaa";
const mintPositionActionParamsEncoded = "0xaaaa";
const settlePairActionParamsEncoded = "0xbbbb";
+ const sweepActionParamsEncoded = "0xcccc";
const unlockData = "0xaaaaa77777AAA";
- const token0Address = "0x1";
+ const token0Address = EthereumConstants.zeroAddress;
const token1Address = "0x2";
const network = AppNetworks.mainnet;
final amount0Desired = BigInt.from(4311);
@@ -1110,31 +1409,43 @@ void main() {
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
);
- when(() => ethereumAbiCoder.encodePacked(["uint8", "uint8"], any())).thenReturn(actionsEncoded);
- when(() => ethereumAbiCoder.encode([
- "tuple(address,address,int32,int24,address)",
- "int24",
- "int24",
- "uint256",
- "uint128",
- "uint128",
- "address",
- "bytes"
- ], any())).thenReturn(mintPositionActionParamsEncoded);
- when(() => ethereumAbiCoder.encode(["address", "address"], [token0Address, token1Address]))
- .thenReturn(settlePairActionParamsEncoded);
+ when(() => ethereumAbiCoder.encodePacked(["uint8", "uint8", "uint8"], any())).thenReturn(actionsEncoded);
+ when(
+ () => ethereumAbiCoder.encode([
+ "tuple(address,address,int32,int24,address)",
+ "int24",
+ "int24",
+ "uint256",
+ "uint128",
+ "uint128",
+ "address",
+ "bytes",
+ ], any()),
+ ).thenReturn(mintPositionActionParamsEncoded);
+ when(
+ () => ethereumAbiCoder.encode(["address", "address"], [token0Address, token1Address]),
+ ).thenReturn(settlePairActionParamsEncoded);
- when(() => ethereumAbiCoder.encode([
- "bytes",
- "bytes[]"
- ], [
+ when(
+ () => ethereumAbiCoder.encode(["address", "address"], [EthereumConstants.zeroAddress, recipient]),
+ ).thenReturn(sweepActionParamsEncoded);
+
+ when(
+ () => ethereumAbiCoder.encode(
+ ["bytes", "bytes[]"],
+ [
actionsEncoded,
- [mintPositionActionParamsEncoded, settlePairActionParamsEncoded]
- ])).thenReturn(unlockData);
+ [mintPositionActionParamsEncoded, settlePairActionParamsEncoded, sweepActionParamsEncoded],
+ ],
+ ),
+ ).thenReturn(unlockData);
when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
).thenAnswer((_) async => transactionResponse);
await sut.sendV4PoolDepositTransaction(
@@ -1151,7 +1462,7 @@ void main() {
);
verify(
- () => positionManagerV4Impl.modifyLiquidities(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
unlockData: unlockData,
deadline: any(named: "deadline"),
ethValue: any(named: "ethValue"),
@@ -1161,66 +1472,17 @@ void main() {
);
test(
- """When calling `sendV4PoolDepositTransaction` it should send the correct deadline to the contract to add liquidity
- (now + deadline)""",
+ """When calling `sendV4PoolDepositTransaction`, the protocol is pancake swap
+ infinity CL and the token0 is native,
+ it should send the correct payload data to the contract to add liquidity""",
() async {
- withClock(Clock(() => DateTime(2022, 1, 1)), () async {
- const token0Address = "0x1";
- const token1Address = "0x2";
- const network = AppNetworks.mainnet;
- final amount0Desired = BigInt.from(4311);
- final amount1Desired = BigInt.from(1031900);
- const deadline = Duration(days: 1);
- final amount0Max = BigInt.from(4312);
- final amount1Max = BigInt.from(1031901);
- final recipient = await signer.address;
- final tickLower = BigInt.from(321);
- final tickUpper = BigInt.from(1222);
-
- final currentYield0 = currentYield.copyWith(
- chainId: network.chainId,
- v4StateView: "0x1",
- poolType: PoolType.v4,
- token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
- token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
- );
-
- when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
- when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
-
- when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
- ).thenAnswer((_) async => transactionResponse);
-
- await sut.sendV4PoolDepositTransaction(
- currentYield0,
- signer,
- deadline: deadline,
- tickLower: tickLower,
- tickUpper: tickUpper,
- amount0toDeposit: amount0Desired,
- amount1ToDeposit: amount1Desired,
- maxAmount0ToDeposit: amount0Max,
- maxAmount1ToDeposit: amount1Max,
- recipient: recipient,
- );
-
- verify(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"),
- deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
- ethValue: any(named: "ethValue"),
- ),
- ).called(1);
- });
- },
- );
+ const actionsEncoded = "0xhvaaa";
+ const mintPositionActionParamsEncoded = "0xaaaa";
+ const closeCurrency0ActionParamsEncoded = "0xbbbb";
+ const closeCurrency1ActionParamsEncoded = "0xxxx";
+ const payloadData = "0xaaaaa77777AAA";
- test(
- """When calling `sendV4PoolDepositTransaction` and none of the tokens are native, it should not send any eth value""",
- () async {
- const token0Address = "0x1";
+ const token0Address = EthereumConstants.zeroAddress;
const token1Address = "0x2";
const network = AppNetworks.mainnet;
final amount0Desired = BigInt.from(4311);
@@ -1232,20 +1494,68 @@ void main() {
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.poolIdToPoolKey(id: any(named: "id"))).thenAnswer(
+ (_) async => (
+ currency0: token0Address,
+ currency1: token1Address,
+ fee: BigInt.from(21),
+ hooks: "",
+ parameters: "",
+ poolManager: "",
+ ),
+ );
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer(
+ (_) async => (
+ lpFee: BigInt.from(21),
+ protocolFee: BigInt.from(21),
+ sqrtPriceX96: BigInt.from(21),
+ tick: BigInt.from(21),
+ ),
+ );
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
v4StateView: "0x1",
poolType: PoolType.v4,
+ v4PoolManager: "0xbvv",
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.pancakeSwapInfinityCL),
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
);
- when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
- when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encodePacked(["uint8", "uint8", "uint8"], any())).thenReturn(actionsEncoded);
+ when(
+ () => ethereumAbiCoder.encode([
+ "tuple(address,address,address,address,uint24,bytes32)",
+ "int24",
+ "int24",
+ "uint256",
+ "uint128",
+ "uint128",
+ "address",
+ "bytes",
+ ], any()),
+ ).thenReturn(mintPositionActionParamsEncoded);
+
+ when(() => ethereumAbiCoder.encode(["address"], [token0Address])).thenReturn(closeCurrency0ActionParamsEncoded);
+ when(() => ethereumAbiCoder.encode(["address"], [token1Address])).thenReturn(closeCurrency1ActionParamsEncoded);
when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
+ () => ethereumAbiCoder.encode(
+ ["bytes", "bytes[]"],
+ [
+ actionsEncoded,
+ [mintPositionActionParamsEncoded, closeCurrency0ActionParamsEncoded, closeCurrency1ActionParamsEncoded],
+ ],
+ ),
+ ).thenReturn(payloadData);
+
+ when(
+ () => pancakeSwapInfinityCLPositionManagerImpl.modifyLiquidities(
+ payload: any(named: "payload"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
).thenAnswer((_) async => transactionResponse);
await sut.sendV4PoolDepositTransaction(
@@ -1262,21 +1572,28 @@ void main() {
);
verify(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"),
+ () => pancakeSwapInfinityCLPositionManagerImpl.modifyLiquidities(
+ payload: payloadData,
deadline: any(named: "deadline"),
- ethValue: null,
+ ethValue: any(named: "ethValue"),
),
).called(1);
},
);
test(
- """When calling `sendV4PoolDepositTransaction` and the token0 is native, it should send the eth value from the
- token0amount""",
+ """When calling `sendV4PoolDepositTransaction`, the protocol is pancake swap
+ infinity CL and the token1 is native,
+ it should send the correct payload data to the contract to add liquidity""",
() async {
- const token0Address = EthereumConstants.zeroAddress;
- const token1Address = "0x2";
+ const actionsEncoded = "0xhvaaa";
+ const mintPositionActionParamsEncoded = "0xaaaa";
+ const closeCurrency0ActionParamsEncoded = "0xbbbb";
+ const closeCurrency1ActionParamsEncoded = "0xxxx";
+ const payloadData = "0xaaaaa77777AAA";
+
+ const token1Address = EthereumConstants.zeroAddress;
+ const token0Address = "0x2";
const network = AppNetworks.mainnet;
final amount0Desired = BigInt.from(4311);
final amount1Desired = BigInt.from(1031900);
@@ -1287,20 +1604,68 @@ void main() {
final tickLower = BigInt.from(321);
final tickUpper = BigInt.from(1222);
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.poolIdToPoolKey(id: any(named: "id"))).thenAnswer(
+ (_) async => (
+ currency0: token0Address,
+ currency1: token1Address,
+ fee: BigInt.from(21),
+ hooks: "",
+ parameters: "",
+ poolManager: "",
+ ),
+ );
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer(
+ (_) async => (
+ lpFee: BigInt.from(21),
+ protocolFee: BigInt.from(21),
+ sqrtPriceX96: BigInt.from(21),
+ tick: BigInt.from(21),
+ ),
+ );
+
final currentYield0 = currentYield.copyWith(
chainId: network.chainId,
v4StateView: "0x1",
poolType: PoolType.v4,
+ v4PoolManager: "0xbvv",
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.pancakeSwapInfinityCL),
token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
);
- when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
- when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encodePacked(["uint8", "uint8", "uint8"], any())).thenReturn(actionsEncoded);
+ when(
+ () => ethereumAbiCoder.encode([
+ "tuple(address,address,address,address,uint24,bytes32)",
+ "int24",
+ "int24",
+ "uint256",
+ "uint128",
+ "uint128",
+ "address",
+ "bytes",
+ ], any()),
+ ).thenReturn(mintPositionActionParamsEncoded);
+
+ when(() => ethereumAbiCoder.encode(["address"], [token0Address])).thenReturn(closeCurrency0ActionParamsEncoded);
+ when(() => ethereumAbiCoder.encode(["address"], [token1Address])).thenReturn(closeCurrency1ActionParamsEncoded);
+
+ when(
+ () => ethereumAbiCoder.encode(
+ ["bytes", "bytes[]"],
+ [
+ actionsEncoded,
+ [mintPositionActionParamsEncoded, closeCurrency0ActionParamsEncoded, closeCurrency1ActionParamsEncoded],
+ ],
+ ),
+ ).thenReturn(payloadData);
when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
+ () => pancakeSwapInfinityCLPositionManagerImpl.modifyLiquidities(
+ payload: any(named: "payload"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
).thenAnswer((_) async => transactionResponse);
await sut.sendV4PoolDepositTransaction(
@@ -1317,21 +1682,27 @@ void main() {
);
verify(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"),
+ () => pancakeSwapInfinityCLPositionManagerImpl.modifyLiquidities(
+ payload: payloadData,
deadline: any(named: "deadline"),
- ethValue: amount0Desired,
+ ethValue: any(named: "ethValue"),
),
).called(1);
},
);
test(
- """When calling `sendV4PoolDepositTransaction` and the token1 is native, it should send the eth value from the
- token1amount""",
+ """When calling `sendV4PoolDepositTransaction` and the token1 is native,
+ it should send the correct unlock data to the contract to add liquidity""",
() async {
- const token0Address = "0x1";
+ const actionsEncoded = "0xhvaaa";
+ const mintPositionActionParamsEncoded = "0xaaaa";
+ const settlePairActionParamsEncoded = "0xbbbb";
+ const sweepActionParamsEncoded = "0xcccc";
+ const unlockData = "0xaaaaa77777AAA";
+
const token1Address = EthereumConstants.zeroAddress;
+ const token0Address = "0x2";
const network = AppNetworks.mainnet;
final amount0Desired = BigInt.from(4311);
final amount1Desired = BigInt.from(1031900);
@@ -1350,12 +1721,43 @@ void main() {
token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
);
- when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
- when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encodePacked(["uint8", "uint8", "uint8"], any())).thenReturn(actionsEncoded);
+ when(
+ () => ethereumAbiCoder.encode([
+ "tuple(address,address,int32,int24,address)",
+ "int24",
+ "int24",
+ "uint256",
+ "uint128",
+ "uint128",
+ "address",
+ "bytes",
+ ], any()),
+ ).thenReturn(mintPositionActionParamsEncoded);
+ when(
+ () => ethereumAbiCoder.encode(["address", "address"], [token0Address, token1Address]),
+ ).thenReturn(settlePairActionParamsEncoded);
+
+ when(
+ () => ethereumAbiCoder.encode(["address", "address"], [EthereumConstants.zeroAddress, recipient]),
+ ).thenReturn(sweepActionParamsEncoded);
+
+ when(
+ () => ethereumAbiCoder.encode(
+ ["bytes", "bytes[]"],
+ [
+ actionsEncoded,
+ [mintPositionActionParamsEncoded, settlePairActionParamsEncoded, sweepActionParamsEncoded],
+ ],
+ ),
+ ).thenReturn(unlockData);
when(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"), deadline: any(named: "deadline"), ethValue: any(named: "ethValue")),
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
).thenAnswer((_) async => transactionResponse);
await sut.sendV4PoolDepositTransaction(
@@ -1372,136 +1774,1718 @@ void main() {
);
verify(
- () => positionManagerV4Impl.modifyLiquidities(
- unlockData: any(named: "unlockData"),
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: unlockData,
deadline: any(named: "deadline"),
- ethValue: amount1Desired,
+ ethValue: any(named: "ethValue"),
),
).called(1);
},
);
test(
- """"When calling `getPoolTick` and the yield protocol is pancakeswap infinity cl,
- it should use the pancakeswap inifity cl pool manager to get the tick""",
+ """When calling `sendV4PoolDepositTransaction` and none of the tokens are native,
+ it should send the correct unlock data to the contract to add liquidity (without sweep)""",
() async {
- final expectedTick = BigInt.from(318675);
-
- when(() => pancakeSwapInfinityCLPoolManager.fromRpcProvider(
- contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl"))).thenReturn(
- pancakeSwapInfinityCLPoolManagerImpl,
- );
+ const actionsEncoded = "0xhvaaa";
+ const mintPositionActionParamsEncoded = "0xaaaa";
+ const settlePairActionParamsEncoded = "0xbbbb";
+ const unlockData = "0xaaaaa77777AAA";
+
+ const token0Address = "0x1";
+ const token1Address = "0x2";
+ const network = AppNetworks.mainnet;
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Max = BigInt.from(4312);
+ final amount1Max = BigInt.from(1031901);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ final currentYield0 = currentYield.copyWith(
+ chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ when(() => ethereumAbiCoder.encodePacked(["uint8", "uint8"], any())).thenReturn(actionsEncoded);
+ when(
+ () => ethereumAbiCoder.encode([
+ "tuple(address,address,int32,int24,address)",
+ "int24",
+ "int24",
+ "uint256",
+ "uint128",
+ "uint128",
+ "address",
+ "bytes",
+ ], any()),
+ ).thenReturn(mintPositionActionParamsEncoded);
+ when(
+ () => ethereumAbiCoder.encode(["address", "address"], [token0Address, token1Address]),
+ ).thenReturn(settlePairActionParamsEncoded);
+
+ when(
+ () => ethereumAbiCoder.encode(
+ ["bytes", "bytes[]"],
+ [
+ actionsEncoded,
+ [mintPositionActionParamsEncoded, settlePairActionParamsEncoded],
+ ],
+ ),
+ ).thenReturn(unlockData);
+
+ when(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ await sut.sendV4PoolDepositTransaction(
+ currentYield0,
+ signer,
+ deadline: deadline,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ amount0toDeposit: amount0Desired,
+ amount1ToDeposit: amount1Desired,
+ maxAmount0ToDeposit: amount0Max,
+ maxAmount1ToDeposit: amount1Max,
+ recipient: recipient,
+ );
+
+ verify(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: unlockData,
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).called(1);
+ },
+ );
+
+ test(
+ """When calling `sendV4PoolDepositTransaction` it should send the correct deadline to the contract to add liquidity
+ (now + deadline)""",
+ () async {
+ withClock(Clock(() => DateTime(2022, 1, 1)), () async {
+ const token0Address = "0x1";
+ const token1Address = "0x2";
+ const network = AppNetworks.mainnet;
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Max = BigInt.from(4312);
+ final amount1Max = BigInt.from(1031901);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ final currentYield0 = currentYield.copyWith(
+ chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+
+ when(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ await sut.sendV4PoolDepositTransaction(
+ currentYield0,
+ signer,
+ deadline: deadline,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ amount0toDeposit: amount0Desired,
+ amount1ToDeposit: amount1Desired,
+ maxAmount0ToDeposit: amount0Max,
+ maxAmount1ToDeposit: amount1Max,
+ recipient: recipient,
+ );
+
+ verify(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).called(1);
+ });
+ },
+ );
+
+ test(
+ """When calling `sendV4PoolDepositTransaction` and none of the tokens are native, it should not send any eth value""",
+ () async {
+ const token0Address = "0x1";
+ const token1Address = "0x2";
+ const network = AppNetworks.mainnet;
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Max = BigInt.from(4312);
+ final amount1Max = BigInt.from(1031901);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ final currentYield0 = currentYield.copyWith(
+ chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+
+ when(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ await sut.sendV4PoolDepositTransaction(
+ currentYield0,
+ signer,
+ deadline: deadline,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ amount0toDeposit: amount0Desired,
+ amount1ToDeposit: amount1Desired,
+ maxAmount0ToDeposit: amount0Max,
+ maxAmount1ToDeposit: amount1Max,
+ recipient: recipient,
+ );
+
+ verify(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: null,
+ ),
+ ).called(1);
+ },
+ );
+
+ test(
+ """When calling `sendV4PoolDepositTransaction` and the token0 is native, it should send the eth value from the
+ token0amount""",
+ () async {
+ const token0Address = EthereumConstants.zeroAddress;
+ const token1Address = "0x2";
+ const network = AppNetworks.mainnet;
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Max = BigInt.from(4312);
+ final amount1Max = BigInt.from(1031901);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ final currentYield0 = currentYield.copyWith(
+ chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+
+ when(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ await sut.sendV4PoolDepositTransaction(
+ currentYield0,
+ signer,
+ deadline: deadline,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ amount0toDeposit: amount0Desired,
+ amount1ToDeposit: amount1Desired,
+ maxAmount0ToDeposit: amount0Max,
+ maxAmount1ToDeposit: amount1Max,
+ recipient: recipient,
+ );
+
+ verify(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: amount0Desired,
+ ),
+ ).called(1);
+ },
+ );
+
+ test(
+ """When calling `sendV4PoolDepositTransaction` and the token1 is native, it should send the eth value from the
+ token1amount""",
+ () async {
+ const token0Address = "0x1";
+ const token1Address = EthereumConstants.zeroAddress;
+ const network = AppNetworks.mainnet;
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Max = BigInt.from(4312);
+ final amount1Max = BigInt.from(1031901);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ final currentYield0 = currentYield.copyWith(
+ chainId: network.chainId,
+ v4StateView: "0x1",
+ poolType: PoolType.v4,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ when(() => ethereumAbiCoder.encodePacked(any(), any())).thenReturn("0x");
+ when(() => ethereumAbiCoder.encode(any(), any())).thenReturn("0x");
+
+ when(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ await sut.sendV4PoolDepositTransaction(
+ currentYield0,
+ signer,
+ deadline: deadline,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ amount0toDeposit: amount0Desired,
+ amount1ToDeposit: amount1Desired,
+ maxAmount0ToDeposit: amount0Max,
+ maxAmount1ToDeposit: amount1Max,
+ recipient: recipient,
+ );
+
+ verify(
+ () => uniswapPositionManagerV4Impl.modifyLiquidities(
+ unlockData: any(named: "unlockData"),
+ deadline: any(named: "deadline"),
+ ethValue: amount1Desired,
+ ),
+ ).called(1);
+ },
+ );
+
+ test(
+ """"When calling `getPoolTick` and the yield protocol is pancakeswap infinity cl,
+ it should use the pancakeswap inifity cl pool manager to get the tick""",
+ () async {
+ final expectedTick = BigInt.from(318675);
+
+ when(
+ () => pancakeSwapInfinityCLPoolManager.fromRpcProvider(
+ contractAddress: any(named: "contractAddress"),
+ rpcUrl: any(named: "rpcUrl"),
+ ),
+ ).thenReturn(pancakeSwapInfinityCLPoolManagerImpl);
+
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer(
+ (_) async =>
+ (sqrtPriceX96: BigInt.from(0), tick: expectedTick, protocolFee: BigInt.from(0), lpFee: BigInt.from(0)),
+ );
+
+ final yield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.pancakeSwapInfinityCL),
+ v4PoolManager: "0x0000001",
+ );
+
+ final receivedPoolTick = await sut.getPoolTick(yield0);
+ expect(receivedPoolTick, expectedTick);
+
+ verify(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: yield0.poolAddress)).called(1);
+ },
+ );
+
+ test(
+ """When calling `getSqrtPriceX96` and the yield protocol is pancakeswap infinity cl,
+ it should use the pancakeswap inifity cl pool manager to get the sqrtPriceX96 from the
+ slot0""",
+ () async {
+ final expectedSqrtPriceX96 = BigInt.parse("3256723627823257362");
+
+ final yield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.pancakeSwapInfinityCL),
+ v4PoolManager: "0x0000001",
+ );
+
+ when(
+ () => pancakeSwapInfinityCLPoolManager.fromRpcProvider(
+ contractAddress: any(named: "contractAddress"),
+ rpcUrl: any(named: "rpcUrl"),
+ ),
+ ).thenReturn(pancakeSwapInfinityCLPoolManagerImpl);
+
+ when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer(
+ (_) async => (
+ sqrtPriceX96: expectedSqrtPriceX96,
+ tick: BigInt.from(0),
+ protocolFee: BigInt.from(0),
+ lpFee: BigInt.from(0),
+ ),
+ );
+
+ final receivedSqrtPriceX96 = await sut.getSqrtPriceX96(yield0);
+
+ expect(receivedSqrtPriceX96, expectedSqrtPriceX96);
+ },
+ );
+
+ test(
+ """When calling `getSqrtPriceX96` and the yield pool is v4,
+ it should use the v4 state view get the sqrtPriceX96 from the
+ slot0""",
+ () async {
+ final expectedSqrtPriceX96 = BigInt.parse("1216426515276100");
+
+ final yield0 = currentYield.copyWith(poolType: PoolType.v4, v4StateView: "0x0000001");
+
+ when(
+ () => stateView.fromRpcProvider(
+ contractAddress: any(named: "contractAddress"),
+ rpcUrl: any(named: "rpcUrl"),
+ ),
+ ).thenReturn(uniswapV4StateViewImpl);
+
+ when(() => uniswapV4StateViewImpl.getSlot0(poolId: any(named: "poolId"))).thenAnswer(
+ (_) async => (
+ sqrtPriceX96: expectedSqrtPriceX96,
+ tick: BigInt.from(0),
+ protocolFee: BigInt.from(0),
+ lpFee: BigInt.from(0),
+ ),
+ );
+
+ final receivedSqrtPriceX96 = await sut.getSqrtPriceX96(yield0);
+
+ expect(receivedSqrtPriceX96, expectedSqrtPriceX96);
+ },
+ );
+
+ test(
+ """When calling `getSqrtPriceX96` and the yield pool is v3,
+ it should use the pool contract get the sqrtPriceX96 from the
+ slot0""",
+ () async {
+ final expectedSqrtPriceX96 = BigInt.parse("907219862715267517621");
+
+ final yield0 = currentYield.copyWith(poolType: PoolType.v3, poolAddress: "0x0000001");
+
+ when(
+ () => uniswapV3Pool.fromRpcProvider(
+ contractAddress: any(named: "contractAddress"),
+ rpcUrl: any(named: "rpcUrl"),
+ ),
+ ).thenReturn(uniswapV3PoolImpl);
+
+ when(() => uniswapV3PoolImpl.slot0()).thenAnswer(
+ (_) async => (
+ feeProtocol: BigInt.from(0),
+ observationCardinality: BigInt.from(0),
+ observationCardinalityNext: BigInt.from(0),
+ observationIndex: BigInt.from(0),
+ sqrtPriceX96: expectedSqrtPriceX96,
+ tick: BigInt.from(0),
+ unlocked: true,
+ ),
+ );
+
+ final receivedSqrtPriceX96 = await sut.getSqrtPriceX96(yield0);
+
+ expect(receivedSqrtPriceX96, expectedSqrtPriceX96);
+ },
+ );
+
+ test(
+ """When calling `getSqrtPriceX96` and the yield pool type
+ is unknown, it should throw an error""",
+ () async {
+ final yield0 = currentYield.copyWith(poolType: PoolType.unknown);
+
+ expect(() async => await sut.getSqrtPriceX96(yield0), throwsA(isA()));
+ },
+ );
+
+ group(
+ 'When the protocol is aerodrome v3 or velodrome v3, it should use aerodrome smart contracts to interact with pools',
+ () {
+ setUp(() {
+ registerFallbackValue((
+ amount0Desired: BigInt.zero,
+ amount0Min: BigInt.zero,
+ amount1Desired: BigInt.zero,
+ amount1Min: BigInt.zero,
+ deadline: BigInt.zero,
+ recipient: "",
+ sqrtPriceX96: BigInt.zero,
+ tickLower: BigInt.zero,
+ tickSpacing: BigInt.zero,
+ tickUpper: BigInt.zero,
+ token0: "",
+ token1: "",
+ ));
+
+ registerFallbackValue(YieldDto.fixture());
+
+ when(
+ () => aerodromePositionManagerV3.fromSigner(
+ contractAddress: any(named: "contractAddress"),
+ signer: any(named: "signer"),
+ ),
+ ).thenReturn(aerodromePositionManagerV3Impl);
+
+ when(
+ () => aerodromeV3Pool.fromRpcProvider(
+ contractAddress: any(named: "contractAddress"),
+ rpcUrl: any(named: "rpcUrl"),
+ ),
+ ).thenReturn(aerodromeV3PoolImpl);
+
+ when(
+ () => aerodromePositionManagerV3.getMintCalldata(params: any(named: "params")),
+ ).thenReturn("0x0000000000000000000000000000000000000000000000000000000000000000");
+ when(
+ () => aerodromePositionManagerV3.getRefundETHCalldata(),
+ ).thenReturn("0x0000000000000000000000000000000000000000000000000000000000000000");
+
+ when(
+ () => aerodromePositionManagerV3Impl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) => Future.value(transactionResponse));
+ });
+
+ test("When the protocol is aerodrome v3 it should use aerodrome v3 pool to get the pool tick", () async {
+ final expectedTick = BigInt.from(1271897);
+
+ when(() => aerodromeV3PoolImpl.slot0()).thenAnswer(
+ (_) async => (
+ observationCardinality: BigInt.from(0),
+ observationCardinalityNext: BigInt.from(0),
+ observationIndex: BigInt.from(0),
+ sqrtPriceX96: BigInt.from(0),
+ tick: expectedTick,
+ unlocked: true,
+ ),
+ );
+
+ final yield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.aerodromeSlipstream),
+ poolType: PoolType.v3,
+ chainId: AppNetworks.mainnet.chainId,
+ );
+
+ final receivedTick = await sut.getPoolTick(yield0);
+
+ expect(receivedTick, expectedTick);
+
+ verify(() => aerodromeV3PoolImpl.slot0()).called(1);
+ });
+
+ test("When the protocol is velodrome v3 it should use aerodrome v3 pool to get the pool tick", () async {
+ final expectedTick = BigInt.from(11111);
+
+ when(() => aerodromeV3PoolImpl.slot0()).thenAnswer(
+ (_) async => (
+ observationCardinality: BigInt.from(0),
+ observationCardinalityNext: BigInt.from(0),
+ observationIndex: BigInt.from(0),
+ sqrtPriceX96: BigInt.from(0),
+ tick: expectedTick,
+ unlocked: true,
+ ),
+ );
+
+ final yield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.velodromeSlipstream),
+ poolType: PoolType.v3,
+ chainId: AppNetworks.mainnet.chainId,
+ );
+
+ final receivedTick = await sut.getPoolTick(yield0);
+
+ expect(receivedTick, expectedTick);
+
+ verify(() => aerodromeV3PoolImpl.slot0()).called(1);
+ });
+
+ test(
+ "when calling with token0 native, it should send a multicall transaction with the mint calldata and a native refund calldata",
+ () async {
+ const mintCalldata = "0x25";
+ const refundCalldata = "0x26";
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.aerodromeSlipstream),
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: EthereumConstants.zeroAddress}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x123"}),
+ );
+
+ when(() => aerodromePositionManagerV3.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
+ when(() => aerodromePositionManagerV3.getRefundETHCalldata()).thenReturn(refundCalldata);
+ when(
+ () => aerodromePositionManagerV3Impl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ final amount0Desired = BigInt.from(100);
+ final amount1Desired = BigInt.from(100);
+ const deadline = Duration.zero;
+ final amount0Min = BigInt.from(12);
+ final amount1Min = BigInt.from(12);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(0);
+ final tickUpper = BigInt.from(0);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => aerodromePositionManagerV3Impl.multicall(
+ data: [mintCalldata, refundCalldata],
+ ethValue: any(named: "ethValue"),
+ ),
+ ).called(1);
+ },
+ );
+
+ test(
+ "when calling with token0 native, it should correctly pass the params to get the mint calldata, with the token0 being the wrapped native address",
+ () async {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const mintCalldata = "0x25";
+ const refundCalldata = "0x26";
+ const token0Address = EthereumConstants.zeroAddress;
+ const token1Address = "0x20172891";
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.aerodromeSlipstream),
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ when(
+ () => aerodromePositionManagerV3.getMintCalldata(params: any(named: "params")),
+ ).thenReturn(mintCalldata);
+ when(() => aerodromePositionManagerV3.getRefundETHCalldata()).thenReturn(refundCalldata);
+ when(
+ () => aerodromePositionManagerV3Impl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Min = BigInt.from(1390);
+ final amount1Min = BigInt.from(432);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => aerodromePositionManagerV3.getMintCalldata(
+ params: (
+ amount0Desired: amount0Desired,
+ amount0Min: amount0Min,
+ amount1Desired: amount1Desired,
+ amount1Min: amount1Min,
+ deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ tickSpacing: BigInt.from(currentYield0.tickSpacing),
+ sqrtPriceX96: BigInt.from(0),
+ token0: network.wrappedNativeTokenAddress,
+ token1: token1Address,
+ ),
+ ),
+ ).called(1);
+ });
+ },
+ );
+
+ test(
+ "when calling with token1 native, it should correctly pass the params to get the mint calldata, with the token1 being the wrapped native address",
+ () async {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const mintCalldata = "0x25";
+ const refundCalldata = "0x26";
+ const token0Address = "0x20172891";
+ const token1Address = EthereumConstants.zeroAddress;
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.aerodromeSlipstream),
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ when(
+ () => aerodromePositionManagerV3.getMintCalldata(params: any(named: "params")),
+ ).thenReturn(mintCalldata);
+ when(() => aerodromePositionManagerV3.getRefundETHCalldata()).thenReturn(refundCalldata);
+ when(
+ () => aerodromePositionManagerV3Impl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ final amount0Desired = BigInt.from(100);
+ final amount1Desired = BigInt.from(31);
+ const deadline = Duration.zero;
+ final amount0Min = BigInt.from(320);
+ final amount1Min = BigInt.from(12);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(32);
+ final tickUpper = BigInt.from(14489);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => aerodromePositionManagerV3.getMintCalldata(
+ params: (
+ amount0Desired: amount0Desired,
+ amount0Min: amount0Min,
+ amount1Desired: amount1Desired,
+ amount1Min: amount1Min,
+ deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ tickSpacing: BigInt.from(currentYield0.tickSpacing),
+ sqrtPriceX96: BigInt.from(0),
+ token0: token0Address,
+ token1: network.wrappedNativeTokenAddress,
+ ),
+ ),
+ ).called(1);
+ });
+ },
+ );
+
+ test("when calling with token0 native, it should correctly send the token0amount as ethValue", () async {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const mintCalldata = "0x25";
+ const refundCalldata = "0x26";
+ const token0Address = EthereumConstants.zeroAddress;
+ const token1Address = "0x20172891";
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.aerodromeSlipstream),
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ when(() => aerodromePositionManagerV3.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
+ when(() => aerodromePositionManagerV3.getRefundETHCalldata()).thenReturn(refundCalldata);
+ when(
+ () => aerodromePositionManagerV3Impl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Min = BigInt.from(1390);
+ final amount1Min = BigInt.from(432);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => aerodromePositionManagerV3Impl.multicall(
+ ethValue: amount0Desired,
+ data: any(named: "data"),
+ ),
+ ).called(1);
+ });
+ });
+
+ test("when calling with token1 native, it should correctly send the token1amount as ethValue", () async {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const mintCalldata = "0x25";
+ const refundCalldata = "0x26";
+ const token1Address = EthereumConstants.zeroAddress;
+ const token0Address = "0x20172891";
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.aerodromeSlipstream),
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ when(() => aerodromePositionManagerV3.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
+ when(() => aerodromePositionManagerV3.getRefundETHCalldata()).thenReturn(refundCalldata);
+ when(
+ () => aerodromePositionManagerV3Impl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Min = BigInt.from(1390);
+ final amount1Min = BigInt.from(432);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
- when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer((_) async => (
- sqrtPriceX96: BigInt.from(0),
- tick: expectedTick,
- protocolFee: BigInt.from(0),
- lpFee: BigInt.from(0),
- ));
+ verify(
+ () => aerodromePositionManagerV3Impl.multicall(
+ ethValue: amount1Desired,
+ data: any(named: "data"),
+ ),
+ ).called(1);
+ });
+ });
- final yield0 = currentYield.copyWith(
- protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.pancakeSwapInfinityCL),
- v4PoolManager: "0x0000001",
+ test(
+ "When there is no native token, it should call mint in the aerodrome position manager passing the correct params",
+ () async {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const token1Address = "0x315768";
+ const token0Address = "0x20172891";
+
+ when(
+ () => aerodromePositionManagerV3Impl.mint(
+ params: any(named: "params"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.aerodromeSlipstream),
+ initialFeeTier: 3982,
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Min = BigInt.from(1390);
+ final amount1Min = BigInt.from(432);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => aerodromePositionManagerV3Impl.mint(
+ params: (
+ token0: token0Address,
+ token1: token1Address,
+ tickSpacing: BigInt.from(currentYield0.tickSpacing),
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
+ sqrtPriceX96: BigInt.from(0),
+ ),
+ ethValue: null,
+ ),
+ ).called(1);
+ });
+ },
);
- final receivedPoolTick = await sut.getPoolTick(yield0);
- expect(receivedPoolTick, expectedTick);
+ test(
+ """When the yield protocol is aerodrome v3 and the pool does not have native token,
+ it should set the sqrtPriceX96 as 0 for the pool and pass it correctly to the mint function""",
+ () {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const token1Address = "0x315768";
+ const token0Address = "0x20172891";
+ final expectedSqrtPriceX96 = BigInt.from(0);
+
+ when(
+ () => aerodromePositionManagerV3Impl.mint(
+ params: any(named: "params"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+ when(() => uniswapV3PoolImpl.slot0()).thenAnswer(
+ (_) async => (
+ feeProtocol: BigInt.from(0),
+ sqrtPriceX96: expectedSqrtPriceX96,
+ tick: BigInt.from(0),
+ observationIndex: BigInt.from(0),
+ observationCardinality: BigInt.from(0),
+ observationCardinalityNext: BigInt.from(0),
+ unlocked: false,
+ ),
+ );
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.aerodromeSlipstream),
+ initialFeeTier: 3982,
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Min = BigInt.from(1390);
+ final amount1Min = BigInt.from(432);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => aerodromePositionManagerV3Impl.mint(
+ params: any(
+ named: "params",
+ that: ObjectParamMatcher((object) => object.sqrtPriceX96 == expectedSqrtPriceX96),
+ ),
+ ethValue: null,
+ ),
+ ).called(1);
+ });
+ },
+ );
- verify(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: yield0.poolAddress)).called(1);
+ test(
+ """When the yield protocol is aerodrome v3 and the pool does have a native token,
+ it should set the sqrtPriceX96 as 0 for the pool and pass it correctly to the mint calldata""",
+ () {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const token1Address = EthereumConstants.zeroAddress;
+ const token0Address = EthereumConstants.zeroAddress;
+ final expectedSqrtPriceX96 = BigInt.from(0);
+
+ when(
+ () => aerodromePositionManagerV3Impl.mint(
+ params: any(named: "params"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+ when(() => uniswapV3PoolImpl.slot0()).thenAnswer(
+ (_) async => (
+ feeProtocol: BigInt.from(0),
+ sqrtPriceX96: expectedSqrtPriceX96,
+ tick: BigInt.from(0),
+ observationIndex: BigInt.from(0),
+ observationCardinality: BigInt.from(0),
+ observationCardinalityNext: BigInt.from(0),
+ unlocked: false,
+ ),
+ );
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.aerodromeSlipstream),
+ initialFeeTier: 3982,
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Min = BigInt.from(1390);
+ final amount1Min = BigInt.from(432);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => aerodromePositionManagerV3.getMintCalldata(
+ params: any(
+ named: "params",
+ that: ObjectParamMatcher((object) => object.sqrtPriceX96 == expectedSqrtPriceX96),
+ ),
+ ),
+ ).called(1);
+ });
+ },
+ );
+
+ test(
+ "When the protocol is aerodrome v3, it should use the aerodrome pool contract to get the sqrtPriceX96",
+ () async {
+ final expectedSqrtPriceX96 = BigInt.from(12718271);
+ when(() => aerodromeV3PoolImpl.slot0()).thenAnswer(
+ (_) async => (
+ sqrtPriceX96: expectedSqrtPriceX96,
+ tick: BigInt.from(0),
+ observationIndex: BigInt.from(0),
+ observationCardinality: BigInt.from(0),
+ observationCardinalityNext: BigInt.from(0),
+ unlocked: false,
+ ),
+ );
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.aerodromeSlipstream),
+ initialFeeTier: 3982,
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ );
+
+ final actualSqrtPriceX96 = await sut.getSqrtPriceX96(currentYield0);
+ expect(actualSqrtPriceX96, expectedSqrtPriceX96);
+
+ verify(() => aerodromeV3PoolImpl.slot0()).called(1);
+ },
+ );
+
+ test(
+ "When the protocol is velodrome v3, it should use the aerodrome pool contract to get the sqrtPriceX96",
+ () async {
+ final expectedSqrtPriceX96 = BigInt.from(90876543);
+ when(() => aerodromeV3PoolImpl.slot0()).thenAnswer(
+ (_) async => (
+ sqrtPriceX96: expectedSqrtPriceX96,
+ tick: BigInt.from(0),
+ observationIndex: BigInt.from(0),
+ observationCardinality: BigInt.from(0),
+ observationCardinalityNext: BigInt.from(0),
+ unlocked: false,
+ ),
+ );
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.velodromeSlipstream),
+ initialFeeTier: 3982,
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ );
+
+ final actualSqrtPriceX96 = await sut.getSqrtPriceX96(currentYield0);
+ expect(actualSqrtPriceX96, expectedSqrtPriceX96);
+
+ verify(() => aerodromeV3PoolImpl.slot0()).called(1);
+ },
+ );
},
);
- test("""When calling `getSqrtPriceX96` and the yield protocol is pancakeswap infinity cl,
- it should use the pancakeswap inifity cl pool manager to get the sqrtPriceX96 from the
- slot0""", () async {
- final expectedSqrtPriceX96 = BigInt.parse("3256723627823257362");
+ group("When the protocol is GLiquid, it should use algebra 1.2.1 smart contracts to interact with the pool", () {
+ setUp(() async {
+ registerFallbackValue((
+ amount0Desired: BigInt.from(0),
+ amount1Desired: BigInt.from(0),
+ deadline: BigInt.from(0),
+ amount0Min: BigInt.from(0),
+ amount1Min: BigInt.from(0),
+ recipient: "",
+ tickLower: BigInt.from(0),
+ tickUpper: BigInt.from(0),
+ deployer: "",
+ token0: "",
+ token1: "",
+ ));
+
+ currentYield = currentYield.copyWith(protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.gliquidV3));
+ when(
+ () => algebra121Pool.fromRpcProvider(
+ contractAddress: any(named: "contractAddress"),
+ rpcUrl: any(named: "rpcUrl"),
+ ),
+ ).thenReturn(algebra121PoolImpl);
- final yield0 = currentYield.copyWith(
- protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.pancakeSwapInfinityCL),
- v4PoolManager: "0x0000001",
- );
+ when(
+ () => algebra121PositionManager.fromSigner(
+ contractAddress: any(named: "contractAddress"),
+ signer: any(named: "signer"),
+ ),
+ ).thenReturn(algebra121PositionManagerImpl);
+ });
+
+ test("When calling 'getPoolTick' it should return the pool tick got from algebra pool 1.2.1", () async {
+ final expectedTick = BigInt.from(12871);
+ when(() => algebra121PoolImpl.globalState()).thenAnswer(
+ (_) async => (
+ price: BigInt.from(0),
+ tick: expectedTick,
+ lastFee: BigInt.from(0),
+ pluginConfig: BigInt.from(0),
+ communityFee: BigInt.from(0),
+ unlocked: false,
+ ),
+ );
- when(() => pancakeSwapInfinityCLPoolManager.fromRpcProvider(
- contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl"))).thenReturn(
- pancakeSwapInfinityCLPoolManagerImpl,
- );
+ final actualTick = await sut.getPoolTick(currentYield);
- when(() => pancakeSwapInfinityCLPoolManagerImpl.getSlot0(id: any(named: "id"))).thenAnswer((_) async => (
- sqrtPriceX96: expectedSqrtPriceX96,
+ expect(actualTick, expectedTick);
+
+ verify(() => algebra121PoolImpl.globalState()).called(1);
+ });
+
+ test("When calling 'getSqrtPriceX96' it should return the price from algebra pool 1.2.1", () async {
+ final expectedSqrtPriceX96 = BigInt.from(12617826517);
+
+ when(() => algebra121PoolImpl.globalState()).thenAnswer(
+ (_) async => (
+ price: expectedSqrtPriceX96,
tick: BigInt.from(0),
- protocolFee: BigInt.from(0),
- lpFee: BigInt.from(0),
- ));
+ lastFee: BigInt.from(0),
+ pluginConfig: BigInt.from(0),
+ communityFee: BigInt.from(0),
+ unlocked: false,
+ ),
+ );
- final receivedSqrtPriceX96 = await sut.getSqrtPriceX96(yield0);
+ final actualSqrtPriceX96 = await sut.getSqrtPriceX96(currentYield);
- expect(receivedSqrtPriceX96, expectedSqrtPriceX96);
- });
+ expect(actualSqrtPriceX96, expectedSqrtPriceX96);
- test("""When calling `getSqrtPriceX96` and the yield pool is v4,
- it should use the v4 state view get the sqrtPriceX96 from the
- slot0""", () async {
- final expectedSqrtPriceX96 = BigInt.parse("1216426515276100");
+ verify(() => algebra121PoolImpl.globalState()).called(1);
+ });
- final yield0 = currentYield.copyWith(
- poolType: PoolType.v4,
- v4StateView: "0x0000001",
- );
+ test(
+ "when calling with token0 native, it should send a multicall transaction with the mint calldata and a native refund calldata",
+ () async {
+ const mintCalldata = "0x25";
+ const refundCalldata = "0x26";
- when(() => stateView.fromRpcProvider(contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl")))
- .thenReturn(
- stateViewImpl,
- );
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.gliquidV3),
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: EthereumConstants.zeroAddress}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: "0x123"}),
+ );
- when(() => stateViewImpl.getSlot0(poolId: any(named: "poolId"))).thenAnswer((_) async => (
- sqrtPriceX96: expectedSqrtPriceX96,
- tick: BigInt.from(0),
- protocolFee: BigInt.from(0),
- lpFee: BigInt.from(0),
- ));
+ when(() => algebra121PositionManager.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
+ when(() => algebra121PositionManager.getRefundNativeTokenCalldata()).thenReturn(refundCalldata);
+ when(
+ () => algebra121PositionManagerImpl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
- final receivedSqrtPriceX96 = await sut.getSqrtPriceX96(yield0);
+ final amount0Desired = BigInt.from(100);
+ final amount1Desired = BigInt.from(100);
+ const deadline = Duration.zero;
+ final amount0Min = BigInt.from(12);
+ final amount1Min = BigInt.from(12);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(0);
+ final tickUpper = BigInt.from(0);
- expect(receivedSqrtPriceX96, expectedSqrtPriceX96);
- });
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
- test("""When calling `getSqrtPriceX96` and the yield pool is v3,
- it should use the pool contract get the sqrtPriceX96 from the
- slot0""", () async {
- final expectedSqrtPriceX96 = BigInt.parse("907219862715267517621");
+ verify(
+ () => algebra121PositionManagerImpl.multicall(
+ data: [mintCalldata, refundCalldata],
+ ethValue: any(named: "ethValue"),
+ ),
+ ).called(1);
+ },
+ );
- final yield0 = currentYield.copyWith(
- poolType: PoolType.v3,
- poolAddress: "0x0000001",
+ test(
+ "when calling with token0 native, it should correctly pass the params to get the mint calldata, with the token0 being the wrapped native address",
+ () async {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const mintCalldata = "0x25";
+ const refundCalldata = "0x26";
+ const token0Address = EthereumConstants.zeroAddress;
+ const token1Address = "0x20172891";
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.gliquidV3),
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ when(() => algebra121PositionManager.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
+ when(() => algebra121PositionManager.getRefundNativeTokenCalldata()).thenReturn(refundCalldata);
+ when(
+ () => algebra121PositionManagerImpl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Min = BigInt.from(1390);
+ final amount1Min = BigInt.from(432);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => algebra121PositionManager.getMintCalldata(
+ params: (
+ amount0Desired: amount0Desired,
+ amount0Min: amount0Min,
+ amount1Desired: amount1Desired,
+ amount1Min: amount1Min,
+ deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ deployer: currentYield0.deployerAddress,
+ token0: network.wrappedNativeTokenAddress,
+ token1: token1Address,
+ ),
+ ),
+ ).called(1);
+ });
+ },
);
- when(() =>
- uniswapV3Pool.fromRpcProvider(contractAddress: any(named: "contractAddress"), rpcUrl: any(named: "rpcUrl")))
- .thenReturn(
- uniswapV3PoolImpl,
+ test(
+ "when calling with token1 native, it should correctly pass the params to get the mint calldata, with the token1 being the wrapped native address",
+ () async {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const mintCalldata = "0x25";
+ const refundCalldata = "0x26";
+ const token0Address = "0x20172891";
+ const token1Address = EthereumConstants.zeroAddress;
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.gliquidV3),
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
+
+ when(() => algebra121PositionManager.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
+ when(() => algebra121PositionManager.getRefundNativeTokenCalldata()).thenReturn(refundCalldata);
+ when(
+ () => algebra121PositionManagerImpl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ final amount0Desired = BigInt.from(100);
+ final amount1Desired = BigInt.from(31);
+ const deadline = Duration.zero;
+ final amount0Min = BigInt.from(320);
+ final amount1Min = BigInt.from(12);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(32);
+ final tickUpper = BigInt.from(14489);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => algebra121PositionManager.getMintCalldata(
+ params: (
+ amount0Desired: amount0Desired,
+ amount0Min: amount0Min,
+ amount1Desired: amount1Desired,
+ amount1Min: amount1Min,
+ deadline: BigInt.from(clock.now().add(deadline).millisecondsSinceEpoch),
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ deployer: currentYield0.deployerAddress,
+ token0: token0Address,
+ token1: network.wrappedNativeTokenAddress,
+ ),
+ ),
+ ).called(1);
+ });
+ },
);
- when(() => uniswapV3PoolImpl.slot0()).thenAnswer((_) async => (
- feeProtocol: BigInt.from(0),
- observationCardinality: BigInt.from(0),
- observationCardinalityNext: BigInt.from(0),
- observationIndex: BigInt.from(0),
- sqrtPriceX96: expectedSqrtPriceX96,
- tick: BigInt.from(0),
- unlocked: true,
- ));
+ test("when calling with token0 native, it should correctly send the token0amount as ethValue", () async {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const mintCalldata = "0x25";
+ const refundCalldata = "0x26";
+ const token0Address = EthereumConstants.zeroAddress;
+ const token1Address = "0x20172891";
- final receivedSqrtPriceX96 = await sut.getSqrtPriceX96(yield0);
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.gliquidV3),
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ );
- expect(receivedSqrtPriceX96, expectedSqrtPriceX96);
- });
+ when(() => algebra121PositionManager.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
+ when(() => algebra121PositionManager.getRefundNativeTokenCalldata()).thenReturn(refundCalldata);
+ when(
+ () => algebra121PositionManagerImpl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Min = BigInt.from(1390);
+ final amount1Min = BigInt.from(432);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => algebra121PositionManagerImpl.multicall(
+ ethValue: amount0Desired,
+ data: any(named: "data"),
+ ),
+ ).called(1);
+ });
+ });
+
+ test(
+ "when the yield has a deployer address set, and the deposit is it a native token, it should pass it to the mint calldata",
+ () async {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const mintCalldata = "0x25";
+ const refundCalldata = "0x26";
+ const token0Address = EthereumConstants.zeroAddress;
+ const token1Address = "0x20172891";
+ const expectedDeployer = "0xdale";
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.gliquidV3),
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ deployerAddress: expectedDeployer,
+ );
+
+ when(() => algebra121PositionManager.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
+ when(() => algebra121PositionManager.getRefundNativeTokenCalldata()).thenReturn(refundCalldata);
+ when(
+ () => algebra121PositionManagerImpl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Min = BigInt.from(1390);
+ final amount1Min = BigInt.from(432);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => algebra121PositionManager.getMintCalldata(
+ params: any(named: "params", that: ObjectParamMatcher((object) => object.deployer == expectedDeployer)),
+ ),
+ ).called(1);
+ });
+ },
+ );
+
+ test(
+ "when the yield has a deployer address set, and the deposit is with erc20, it should pass it to the mint function",
+ () async {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const token0Address = "0x123";
+ const token1Address = "0x20172891";
+ const expectedDeployer = "0xdalepapi";
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.gliquidV3),
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ deployerAddress: expectedDeployer,
+ );
+
+ when(
+ () => algebra121PositionManagerImpl.mint(params: any(named: "params")),
+ ).thenAnswer((_) async => transactionResponse);
+
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Min = BigInt.from(1390);
+ final amount1Min = BigInt.from(432);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => algebra121PositionManagerImpl.mint(
+ params: any(named: "params", that: ObjectParamMatcher((object) => object.deployer == expectedDeployer)),
+ ),
+ ).called(1);
+ });
+ },
+ );
- test("""When calling `getSqrtPriceX96` and the yield pool type
- is unknown, it should throw an error""", () async {
- final yield0 = currentYield.copyWith(
- poolType: PoolType.unknown,
+ test(
+ "when the yield has a deployer address as zero address, and the deposit is with erc20, it should pass it to the mint function",
+ () async {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const token0Address = "0x123";
+ const token1Address = "0x20172891";
+ const expectedDeployer = EthereumConstants.zeroAddress;
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.gliquidV3),
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ deployerAddress: expectedDeployer,
+ );
+
+ when(
+ () => algebra121PositionManagerImpl.mint(params: any(named: "params")),
+ ).thenAnswer((_) async => transactionResponse);
+
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Min = BigInt.from(1390);
+ final amount1Min = BigInt.from(432);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => algebra121PositionManagerImpl.mint(
+ params: any(
+ named: "params",
+ that: ObjectParamMatcher((object) => object.deployer == EthereumConstants.zeroAddress),
+ ),
+ ),
+ ).called(1);
+ });
+ },
);
- expect(() async => await sut.getSqrtPriceX96(yield0), throwsA(isA()));
+ test(
+ "when the yield has a deployer address of address zero, and the deposit is it a native token, it should pass it to the mint calldata",
+ () async {
+ withClock(Clock.fixed(DateTime(2028)), () async {
+ const mintCalldata = "0x25";
+ const refundCalldata = "0x26";
+ const token0Address = EthereumConstants.zeroAddress;
+ const token1Address = "0x20172891";
+
+ const network = AppNetworks.mainnet;
+ final currentYield0 = currentYield.copyWith(
+ protocol: ProtocolDto.fixture().copyWith(id: ProtocolId.gliquidV3),
+ poolType: PoolType.v3,
+ chainId: network.chainId,
+ token0: TokenDto.fixture().copyWith(addresses: {network.chainId: token0Address}),
+ token1: TokenDto.fixture().copyWith(addresses: {network.chainId: token1Address}),
+ deployerAddress: EthereumConstants.zeroAddress,
+ );
+
+ when(() => algebra121PositionManager.getMintCalldata(params: any(named: "params"))).thenReturn(mintCalldata);
+ when(() => algebra121PositionManager.getRefundNativeTokenCalldata()).thenReturn(refundCalldata);
+ when(
+ () => algebra121PositionManagerImpl.multicall(
+ data: any(named: "data"),
+ ethValue: any(named: "ethValue"),
+ ),
+ ).thenAnswer((_) async => transactionResponse);
+
+ final amount0Desired = BigInt.from(4311);
+ final amount1Desired = BigInt.from(1031900);
+ const deadline = Duration(days: 1);
+ final amount0Min = BigInt.from(1390);
+ final amount1Min = BigInt.from(432);
+ final recipient = await signer.address;
+ final tickLower = BigInt.from(321);
+ final tickUpper = BigInt.from(1222);
+
+ await sut.sendV3PoolDepositTransaction(
+ currentYield0,
+ signer,
+ amount0Desired: amount0Desired,
+ amount1Desired: amount1Desired,
+ deadline: deadline,
+ amount0Min: amount0Min,
+ amount1Min: amount1Min,
+ recipient: recipient,
+ tickLower: tickLower,
+ tickUpper: tickUpper,
+ );
+
+ verify(
+ () => algebra121PositionManager.getMintCalldata(
+ params: any(
+ named: "params",
+ that: ObjectParamMatcher((object) => object.deployer == EthereumConstants.zeroAddress),
+ ),
+ ),
+ ).called(1);
+ });
+ },
+ );
});
}
diff --git a/test/core/v4_pool_constants_test.dart b/test/core/v4_pool_constants_test.dart
index 09e994b..dd380c2 100644
--- a/test/core/v4_pool_constants_test.dart
+++ b/test/core/v4_pool_constants_test.dart
@@ -7,10 +7,14 @@ void main() {
});
test('settlePairActionValue should return the correct value', () {
- expect(V4PoolConstants.settlePairActionValue, 0x0d);
+ expect(V4PoolConstants.uniswapSettlePairActionValue, 0x0d);
});
test('sweepActionValue should return the correct value', () {
- expect(V4PoolConstants.sweepActionValue, 0x14);
+ expect(V4PoolConstants.uniswapSweepActionValue, 0x14);
+ });
+
+ test("close currency should return the correct value", () {
+ expect(V4PoolConstants.pancakeSwapCloseCurrencyActionValue, 0x12);
});
}
diff --git a/test/matchers.dart b/test/matchers.dart
index f7da309..64945eb 100644
--- a/test/matchers.dart
+++ b/test/matchers.dart
@@ -15,3 +15,17 @@ class ExpectedMatcher extends Matcher {
return true;
}
}
+
+class ObjectParamMatcher extends Matcher {
+ ObjectParamMatcher(this.matching);
+
+ final bool Function(dynamic object) matching;
+
+ @override
+ Description describe(Description description) => description.add("dale");
+
+ @override
+ bool matches(item, Map matchState) {
+ return matching(item);
+ }
+}
diff --git a/test/mocks.dart b/test/mocks.dart
index 657af0d..cfe2bf1 100644
--- a/test/mocks.dart
+++ b/test/mocks.dart
@@ -11,8 +11,13 @@ import 'package:url_launcher_platform_interface/link.dart';
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
import 'package:web3kit/core/dtos/transaction_response.dart';
import 'package:web3kit/web3kit.dart';
+import 'package:zup_app/abis/aerodrome_v3_pool.abi.g.dart';
+import 'package:zup_app/abis/aerodrome_v3_position_manager.abi.g.dart';
+import 'package:zup_app/abis/algebra/v1.2.1/pool.abi.g.dart' as algebra_1_2_1_pool;
+import 'package:zup_app/abis/algebra/v1.2.1/position_manager.abi.g.dart' as algebra_1_2_1_position_manager;
import 'package:zup_app/abis/erc_20.abi.g.dart';
import 'package:zup_app/abis/pancake_swap_infinity_cl_pool_manager.abi.g.dart';
+import 'package:zup_app/abis/pancake_swap_infinity_cl_position_manager.abi.g.dart';
import 'package:zup_app/abis/uniswap_permit2.abi.g.dart';
import 'package:zup_app/abis/uniswap_v3_pool.abi.g.dart';
import 'package:zup_app/abis/uniswap_v3_position_manager.abi.g.dart';
@@ -92,8 +97,20 @@ class PancakeSwapInfinityCLPoolManagerMock extends Mock implements PancakeSwapIn
class PancakeSwapInfinityCLPoolManagerImplMock extends Mock implements PancakeSwapInfinityClPoolManagerImpl {}
+class PancakeSwapInfinityCLPositionManagerMock extends Mock implements PancakeSwapInfinityClPositionManager {}
+
+class PancakeSwapInfinityCLPositionManagerImplMock extends Mock implements PancakeSwapInfinityClPositionManagerImpl {}
+
class UniswapV3PoolImplMock extends Mock implements UniswapV3PoolImpl {}
+class Algebra121PositionManagerMock extends Mock implements algebra_1_2_1_position_manager.PositionManager {}
+
+class Algebra121PositionManagerImplMock extends Mock implements algebra_1_2_1_position_manager.PositionManagerImpl {}
+
+class Algebra121PoolMock extends Mock implements algebra_1_2_1_pool.Pool {}
+
+class Algebra121PoolImplMock extends Mock implements algebra_1_2_1_pool.PoolImpl {}
+
class UniswapV3PoolMock extends Mock implements UniswapV3Pool {}
class WalletMock extends Mock implements Wallet {}
@@ -120,6 +137,14 @@ class ZupHolderMock extends Mock implements ZupHolder {}
class ProtocolRepositoryMock extends Mock implements ProtocolRepository {}
+class AerodromeV3PositionManagerMock extends Mock implements AerodromeV3PositionManager {}
+
+class AerodromeV3PoolMock extends Mock implements AerodromeV3Pool {}
+
+class AerodromeV3PoolImplMock extends Mock implements AerodromeV3PoolImpl {}
+
+class AerodromeV3PositionManagerImplMock extends Mock implements AerodromeV3PositionManagerImpl {}
+
class ChangeNotifierMock extends Mock with ChangeNotifier {
void notify() => notifyListeners();
}
diff --git a/test/widgets/goldens/yield_card_30d.png b/test/widgets/goldens/yield_card_30d.png
index ca9d642..c547c19 100644
Binary files a/test/widgets/goldens/yield_card_30d.png and b/test/widgets/goldens/yield_card_30d.png differ
diff --git a/test/widgets/goldens/yield_card_7d.png b/test/widgets/goldens/yield_card_7d.png
index b08c0fb..c35f2fe 100644
Binary files a/test/widgets/goldens/yield_card_7d.png and b/test/widgets/goldens/yield_card_7d.png differ
diff --git a/test/widgets/goldens/yield_card_90d.png b/test/widgets/goldens/yield_card_90d.png
index dcbb607..45c1785 100644
Binary files a/test/widgets/goldens/yield_card_90d.png and b/test/widgets/goldens/yield_card_90d.png differ
diff --git a/web/index.html b/web/index.html
index 293aa35..3b64da5 100644
--- a/web/index.html
+++ b/web/index.html
@@ -66,6 +66,6 @@
inject();
-
+