@paraswap/dex-lib
Advanced tools
Comparing version 4.0.22 to 4.0.23
import { Interface } from '@ethersproject/abi'; | ||
import { Token, Address, ExchangePrices, PoolPrices, AdapterExchangeParam, SimpleExchangeParam, PoolLiquidity, Logger, NumberAsString, DexExchangeParam } from '../../types'; | ||
import { Token, Address, ExchangePrices, PoolPrices, AdapterExchangeParam, SimpleExchangeParam, PoolLiquidity, Logger } from '../../types'; | ||
import { SwapSide, Network } from '../../constants'; | ||
@@ -31,5 +31,4 @@ import { IDex } from '../../dex/idex'; | ||
getSimpleParam(srcToken: string, destToken: string, srcAmount: string, destAmount: string, data: AaveV1Data, side: SwapSide): Promise<SimpleExchangeParam>; | ||
getDexParam(srcToken: Address, destToken: Address, srcAmount: NumberAsString, destAmount: NumberAsString, recipient: Address, data: AaveV1Data, side: SwapSide): DexExchangeParam; | ||
updatePoolState(): Promise<void>; | ||
getTopPoolsForToken(tokenAddress: Address, limit: number): Promise<PoolLiquidity[]>; | ||
} |
@@ -142,25 +142,2 @@ "use strict"; | ||
} | ||
// DEAD | ||
getDexParam(srcToken, destToken, srcAmount, destAmount, recipient, data, side) { | ||
const amount = side === constants_1.SwapSide.SELL ? srcAmount : destAmount; | ||
const [Interface, swapFunction, swapFunctionParams, swapCallee] = (() => { | ||
if (data.fromAToken) { | ||
return [this.aContract, AaveV1Functions.redeem, [amount], srcToken]; | ||
} | ||
return [ | ||
this.aavePool, | ||
AaveV1Functions.deposit, | ||
[srcToken, amount, REF_CODE], | ||
AAVE_LENDING_POOL, | ||
]; | ||
})(); | ||
const exchangeData = Interface.encodeFunctionData(swapFunction, swapFunctionParams); | ||
return { | ||
needWrapNative: this.needWrapNative, | ||
dexFuncHasRecipient: false, | ||
exchangeData, | ||
targetExchange: swapCallee, | ||
returnAmountPos: undefined, | ||
}; | ||
} | ||
// This is called once before getTopPoolsForToken is | ||
@@ -167,0 +144,0 @@ // called for multiple tokens. This can be helpful to |
@@ -24,3 +24,3 @@ "use strict"; | ||
[constants_1.Network.BASE]: { | ||
subgraphURL: 'https://api.studio.thegraph.com/query/24660/balancer-base-v2/version/latest', | ||
subgraphURL: 'E7XyutxXVLrp8njmjF16Hh38PCJuHm12RRyMt5ma4ctX', | ||
vaultAddress: '0xBA12222222228d8Ba445958a75a0704d566BF2C8', | ||
@@ -27,0 +27,0 @@ }, |
@@ -6,5 +6,5 @@ "use strict"; | ||
exports.testConfig = { | ||
[constants_1.Network.ARBITRUM]: [ | ||
[constants_1.Network.MAINNET]: [ | ||
{ | ||
srcToken: 'WETH', | ||
srcToken: 'USDT', | ||
destToken: 'USDC', | ||
@@ -16,3 +16,3 @@ amount: '10000', | ||
srcToken: 'USDC', | ||
destToken: 'WETH', | ||
destToken: 'USDT', | ||
amount: '10000', | ||
@@ -19,0 +19,0 @@ swapSide: constants_1.SwapSide.SELL, |
import { Interface } from '@ethersproject/abi'; | ||
import { SwapSide } from '../constants'; | ||
import { AdapterExchangeParam, Address, DexExchangeParam, NumberAsString, SimpleExchangeParam } from '../types'; | ||
import { AdapterExchangeParam, Address, SimpleExchangeParam } from '../types'; | ||
import { IDexTxBuilder } from './idex'; | ||
@@ -54,4 +54,3 @@ import { SimpleExchange } from './simple-exchange'; | ||
getSimpleParam(srcToken: string, destToken: string, srcAmount: string, destAmount: string, data: JarvisData, side: SwapSide): Promise<SimpleExchangeParam>; | ||
getDexParam(srcToken: Address, destToken: Address, srcAmount: NumberAsString, destAmount: NumberAsString, recipient: Address, data: JarvisData, side: SwapSide): DexExchangeParam; | ||
} | ||
export {}; |
@@ -11,3 +11,2 @@ "use strict"; | ||
const Jarvis_json_1 = __importDefault(require("../abi/Jarvis.json")); | ||
const utils_1 = require("../executor/utils"); | ||
const THIRTY_MINUTES = 60 * 30; | ||
@@ -104,59 +103,2 @@ var JarvisFunctions; | ||
} | ||
getDexParam(srcToken, destToken, srcAmount, destAmount, recipient, data, side) { | ||
const swapFunction = data.method; | ||
const timestamp = (Date.now() / 1000 + THIRTY_MINUTES).toFixed(0); | ||
let swapFunctionParams; | ||
let outputName; | ||
switch (swapFunction) { | ||
case JarvisFunctions.mint: | ||
swapFunctionParams = [ | ||
data.derivatives, | ||
destAmount, | ||
srcAmount, | ||
data.fee, | ||
timestamp, | ||
recipient, | ||
]; | ||
outputName = 'syntheticTokensMinted'; | ||
break; | ||
case JarvisFunctions.redeem: | ||
swapFunctionParams = [ | ||
data.derivatives, | ||
srcAmount, | ||
destAmount, | ||
data.fee, | ||
timestamp, | ||
recipient, | ||
]; | ||
outputName = 'collateralRedeemed'; | ||
break; | ||
case JarvisFunctions.exchange: | ||
swapFunctionParams = [ | ||
data.derivatives, | ||
data.pools[1], | ||
data.destDerivatives, | ||
srcAmount, | ||
destAmount, | ||
data.fee, | ||
timestamp, | ||
recipient, | ||
]; | ||
outputName = 'destNumTokensMinted'; | ||
break; | ||
default: | ||
throw new Error(`Unknown function ${swapFunction}`); | ||
} | ||
const swapData = this.poolInterface.encodeFunctionData(swapFunction, [ | ||
swapFunctionParams, | ||
]); | ||
return { | ||
needWrapNative: this.needWrapNative, | ||
dexFuncHasRecipient: true, | ||
exchangeData: swapData, | ||
targetExchange: data.pools[0], | ||
returnAmountPos: side === constants_1.SwapSide.SELL | ||
? (0, utils_1.extractReturnAmountPosition)(this.poolInterface, swapFunction, outputName) | ||
: undefined, | ||
}; | ||
} | ||
} | ||
@@ -163,0 +105,0 @@ exports.Jarvis = Jarvis; |
@@ -16,3 +16,3 @@ "use strict"; | ||
[constants_1.Network.BASE]: { | ||
subgraphURL: 'https://api.studio.thegraph.com/query/42519/maverick-base/version/latest', | ||
subgraphURL: 'CSxkHjxpG1TxTBQMn55uG1DWpdD4Lsix4RNX4RTLvK4T', | ||
routerAddress: '0x32AED3Bce901DA12ca8489788F3A99fCe1056e14', | ||
@@ -19,0 +19,0 @@ poolInspectorAddress: '0x65A3AD03Be97619284bA7AA1E3Ca05638B9d6364', |
import { Interface } from '@ethersproject/abi'; | ||
import { Token, Address, ExchangePrices, PoolPrices, AdapterExchangeParam, SimpleExchangeParam, PoolLiquidity, Logger, NumberAsString, DexExchangeParam } from '../../types'; | ||
import { Token, Address, ExchangePrices, PoolPrices, AdapterExchangeParam, SimpleExchangeParam, PoolLiquidity, Logger } from '../../types'; | ||
import { SwapSide, Network } from '../../constants'; | ||
@@ -60,5 +60,4 @@ import { IDex } from '../../dex/idex'; | ||
getSimpleParam(srcToken: string, destToken: string, srcAmount: string, destAmount: string, data: PlatypusData, side: SwapSide): Promise<SimpleExchangeParam>; | ||
getDexParam(srcToken: Address, destToken: Address, srcAmount: NumberAsString, destAmount: NumberAsString, recipient: Address, data: PlatypusData, side: SwapSide): DexExchangeParam; | ||
updatePoolState(): Promise<void>; | ||
getTopPoolsForToken(tokenAddress: Address, limit: number): Promise<PoolLiquidity[]>; | ||
} |
@@ -46,3 +46,2 @@ "use strict"; | ||
const oracle_json_1 = __importDefault(require("../../abi/platypus/oracle.json")); | ||
const utils_2 = require("../../executor/utils"); | ||
class Platypus extends simple_exchange_1.SimpleExchange { | ||
@@ -367,46 +366,2 @@ constructor(network, dexKey, dexHelper, adapters = config_1.Adapters[network]) { | ||
} | ||
getDexParam(srcToken, destToken, srcAmount, destAmount, recipient, data, side) { | ||
const iface = (0, utils_1.isETHAddress)(srcToken) | ||
? Platypus.avaxPoolInterface | ||
: (0, utils_1.isETHAddress)(destToken) | ||
? Platypus.avaxPoolInterface | ||
: Platypus.poolInterface; | ||
const swapFunction = (0, utils_1.isETHAddress)(srcToken) | ||
? 'swapFromETH' | ||
: (0, utils_1.isETHAddress)(destToken) | ||
? 'swapToETH' | ||
: 'swap'; | ||
const swapData = (0, utils_1.isETHAddress)(srcToken) | ||
? iface.encodeFunctionData(swapFunction, [ | ||
destToken, | ||
1, | ||
recipient, | ||
(0, simple_exchange_1.getLocalDeadlineAsFriendlyPlaceholder)(), | ||
]) | ||
: (0, utils_1.isETHAddress)(destToken) | ||
? iface.encodeFunctionData(swapFunction, [ | ||
srcToken, | ||
srcAmount, | ||
1, | ||
recipient, | ||
(0, simple_exchange_1.getLocalDeadlineAsFriendlyPlaceholder)(), | ||
]) | ||
: iface.encodeFunctionData(swapFunction, [ | ||
srcToken, | ||
destToken, | ||
srcAmount, | ||
1, | ||
recipient, | ||
(0, simple_exchange_1.getLocalDeadlineAsFriendlyPlaceholder)(), | ||
]); | ||
return { | ||
needWrapNative: this.needWrapNative, | ||
dexFuncHasRecipient: true, | ||
exchangeData: swapData, | ||
targetExchange: data.pool, | ||
returnAmountPos: side === constants_1.SwapSide.SELL | ||
? (0, utils_2.extractReturnAmountPosition)(iface, swapFunction, 'actualToAmount') | ||
: undefined, | ||
}; | ||
} | ||
// This is called once before getTopPoolsForToken is | ||
@@ -413,0 +368,0 @@ // called for multiple tokens. This can be helpful to |
@@ -54,3 +54,10 @@ "use strict"; | ||
exports.StablePool = StablePool; | ||
StablePool.dexKeys = ['nerve', 'ironv2', 'snowball', 'axial']; | ||
StablePool.dexKeys = [ | ||
'nerve', | ||
'saddle', | ||
'ironv2', | ||
'snowball', | ||
'axial', | ||
'zyberswapstable', | ||
]; | ||
//# sourceMappingURL=stable-pool.js.map |
import { Interface } from '@ethersproject/abi'; | ||
import { Token, Address, ExchangePrices, PoolPrices, AdapterExchangeParam, SimpleExchangeParam, PoolLiquidity, Logger, NumberAsString, DexExchangeParam } from '../../types'; | ||
import { Token, Address, ExchangePrices, PoolPrices, AdapterExchangeParam, SimpleExchangeParam, PoolLiquidity, Logger } from '../../types'; | ||
import { SwapSide, Network } from '../../constants'; | ||
@@ -53,3 +53,2 @@ import { IDex } from '../../dex/idex'; | ||
getSimpleParam(srcToken: string, destToken: string, srcAmount: string, destAmount: string, data: SwaapV1Data, side: SwapSide): Promise<SimpleExchangeParam>; | ||
getDexParam(srcToken: Address, destToken: Address, srcAmount: NumberAsString, destAmount: NumberAsString, recipient: Address, data: SwaapV1Data, side: SwapSide): DexExchangeParam; | ||
getTopPoolsForToken(tokenAddress: Address, count: number): Promise<PoolLiquidity[]>; | ||
@@ -56,0 +55,0 @@ getTopPoolsForTokens(tokenAddresses: Address[], count: number, blockNumber: number | null): Promise<SubgraphPoolBase[]>; |
@@ -40,3 +40,2 @@ "use strict"; | ||
const PoolQuotations_1 = require("./libraries/PoolQuotations"); | ||
const utils_2 = require("../../executor/utils"); | ||
class SwaapV1 extends simple_exchange_1.SimpleExchange { | ||
@@ -164,15 +163,2 @@ constructor(network, dexKey, dexHelper, adapters = config_1.Adapters[network]) { | ||
} | ||
getDexParam(srcToken, destToken, srcAmount, destAmount, recipient, data, side) { | ||
const [params, functionName] = this.getSwaapV1Param(srcToken, destToken, srcAmount, destAmount, data, side); | ||
const swapData = SwaapV1.poolInterface.encodeFunctionData(functionName, params); | ||
return { | ||
needWrapNative: this.needWrapNative, | ||
dexFuncHasRecipient: false, | ||
exchangeData: swapData, | ||
targetExchange: data.pool, | ||
returnAmountPos: side === constants_1.SwapSide.SELL | ||
? (0, utils_2.extractReturnAmountPosition)(SwaapV1.poolInterface, functionName, 'tokenAmountOut') | ||
: undefined, | ||
}; | ||
} | ||
// // Returns list of top pools based on liquidity. Max | ||
@@ -179,0 +165,0 @@ // // limit number pools should be returned. |
@@ -117,3 +117,3 @@ "use strict"; | ||
initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, | ||
subgraphURL: 'https://api.studio.thegraph.com/query/48211/uniswap-v3-base/version/latest', | ||
subgraphURL: 'GqzP4Xaehti8KSfQmv3ZctFSjnSUYZ4En5NRsiTbvZpz', | ||
}, | ||
@@ -120,0 +120,0 @@ }, |
@@ -5,5 +5,27 @@ import { Interface } from '@ethersproject/abi'; | ||
import type { IDexTxBuilder } from '../idex'; | ||
import type { AdapterExchangeParam, Address, DexExchangeParam, NumberAsString, SimpleExchangeParam, TxInfo } from '../../types'; | ||
import { type ZeroXData, type ZeroXParam } from './types'; | ||
import type { AdapterExchangeParam, Address, NumberAsString, SimpleExchangeParam, TxInfo } from '../../types'; | ||
import type { ZeroXSignedOrder } from './types'; | ||
import { IDexHelper } from '../../dex-helper'; | ||
declare type ZeroXData = { | ||
version: number; | ||
order: ZeroXSignedOrder; | ||
}; | ||
declare type SwapOnZeroXParam = [ | ||
srcToken: Address, | ||
destToken: Address, | ||
srcAmount: NumberAsString, | ||
destAmount: NumberAsString, | ||
exchange: Address, | ||
payload: string | ||
]; | ||
declare type SwapOnZeroXWithPermitParam = [ | ||
srcToken: Address, | ||
destToken: Address, | ||
srcAmount: NumberAsString, | ||
destAmount: NumberAsString, | ||
exchange: Address, | ||
payload: string, | ||
permit: string | ||
]; | ||
declare type ZeroXParam = SwapOnZeroXParam | SwapOnZeroXWithPermitParam; | ||
export declare class ZeroX extends SimpleExchange implements IDexTxBuilder<ZeroXData, ZeroXParam> { | ||
@@ -20,5 +42,5 @@ static dexKeys: string[]; | ||
getSimpleParam(src: Address, dest: Address, srcAmount: NumberAsString, destAmount: NumberAsString, data: ZeroXData, side: SwapSide): Promise<SimpleExchangeParam>; | ||
getDexParam(_srcToken: Address, _destToken: Address, srcAmount: NumberAsString, destAmount: NumberAsString, _recipient: Address, data: ZeroXData, side: SwapSide): DexExchangeParam; | ||
getDirectParam(srcToken: Address, destToken: Address, srcAmount: NumberAsString, destAmount: NumberAsString, expectedAmount: NumberAsString, data: ZeroXData, side: SwapSide, permit: string, uuid: string, feePercent: NumberAsString, deadline: NumberAsString, partner: string, beneficiary: string, contractMethod: string): TxInfo<ZeroXParam>; | ||
getDirectParam(srcToken: Address, destToken: Address, srcAmount: NumberAsString, destAmount: NumberAsString, expectedAmount: NumberAsString, data: ZeroXData, side: SwapSide, permit: string, uuid: string, feePercent: NumberAsString, deadline: NumberAsString, partner: string, beneficiary: string, contractMethod?: string): TxInfo<ZeroXParam>; | ||
static getDirectFunctionName(): string[]; | ||
} | ||
export {}; |
@@ -16,4 +16,16 @@ "use strict"; | ||
const order_1 = require("./order"); | ||
const types_1 = require("./types"); | ||
const config_1 = require("./config"); | ||
const ZRX_EXCHANGE = { | ||
1: { | ||
2: '0x080bf510fcbf18b91105470639e9561022937712', | ||
3: '0x61935CbDd02287B511119DDb11Aeb42F1593b7Ef', | ||
4: '0xdef1c0ded9bec7f1a1670819833240f027b25eff', | ||
}, | ||
56: { | ||
2: '0x3F93C3D9304a70c9104642AB8cD37b1E2a7c203A', | ||
4: '0xdef1c0ded9bec7f1a1670819833240f027b25eff', | ||
}, | ||
137: { | ||
4: '0xdef1c0ded9bec7f1a1670819833240f027b25eff', | ||
}, | ||
}; | ||
const ZRX_ABI = { | ||
@@ -24,2 +36,23 @@ 2: zrx_v2_json_1.default, | ||
}; | ||
const ZRX_EXCHANGE_ERC20PROXY = { | ||
1: { | ||
1: '0x95E6F48254609A6ee006F7D493c8e5fB97094ceF', | ||
2: '0x95E6F48254609A6ee006F7D493c8e5fB97094ceF', | ||
4: '0xdef1c0ded9bec7f1a1670819833240f027b25eff', | ||
}, | ||
56: { | ||
2: '0xCF21d4b7a265FF779accBA55Ace0F56C8cE6e379', | ||
4: '0xdef1c0ded9bec7f1a1670819833240f027b25eff', | ||
}, | ||
137: { | ||
4: '0xdef1c0ded9bec7f1a1670819833240f027b25eff', | ||
}, | ||
}; | ||
var ZeroXFunctions; | ||
(function (ZeroXFunctions) { | ||
ZeroXFunctions["swapOnZeroXv2"] = "swapOnZeroXv2"; | ||
ZeroXFunctions["swapOnZeroXv4"] = "swapOnZeroXv4"; | ||
ZeroXFunctions["swapOnZeroXv2WithPermit"] = "swapOnZeroXv2WithPermit"; | ||
ZeroXFunctions["swapOnZeroXv4WithPermit"] = "swapOnZeroXv4WithPermit"; | ||
})(ZeroXFunctions || (ZeroXFunctions = {})); | ||
class ZeroX extends simple_exchange_1.SimpleExchange { | ||
@@ -32,3 +65,3 @@ constructor(dexHelper) { | ||
getExchange(data) { | ||
return config_1.ZRX_EXCHANGE[this.network][data.version]; | ||
return ZRX_EXCHANGE[this.network][data.version]; | ||
} | ||
@@ -140,45 +173,4 @@ buildSimpleSwapData(data, srcAmount) { | ||
const networkFees = '0'; | ||
return this.buildSimpleParamWithoutWETHConversion(src, srcAmount, dest, destAmount, swapData, this.getExchange(data), config_1.ZRX_EXCHANGE_ERC20PROXY[this.network][data.version], networkFees); | ||
return this.buildSimpleParamWithoutWETHConversion(src, srcAmount, dest, destAmount, swapData, this.getExchange(data), ZRX_EXCHANGE_ERC20PROXY[this.network][data.version], networkFees); | ||
} | ||
getDexParam(_srcToken, _destToken, srcAmount, destAmount, _recipient, data, side) { | ||
if (side === constants_1.SwapSide.BUY) { | ||
// Adjust the srcAmount according to the exact order price (rounding up) | ||
if (data.version === 4) { | ||
const order = data.order; | ||
if (BigInt(destAmount) > BigInt(order.makerAmount)) { | ||
throw new Error(`ZeroX destAmount ${destAmount} > makerAmount ${order.makerAmount}`); | ||
} | ||
const calc = (BigInt(destAmount) * BigInt(order.takerAmount) + | ||
BigInt(order.makerAmount) - | ||
1n) / | ||
BigInt(order.makerAmount); | ||
if (calc > BigInt(srcAmount)) { | ||
throw new Error(`ZeroX calc ${calc} > srcAmount ${srcAmount}`); | ||
} | ||
srcAmount = calc.toString(); | ||
} | ||
else { | ||
const order = data.order; | ||
if (BigInt(destAmount) > BigInt(order.makerAssetAmount)) { | ||
throw new Error(`ZeroX destAmount ${destAmount} > makerAmount ${order.makerAssetAmount}`); | ||
} | ||
const calc = (BigInt(destAmount) * BigInt(order.takerAssetAmount) + | ||
BigInt(order.makerAssetAmount) - | ||
1n) / | ||
BigInt(order.makerAssetAmount); | ||
if (calc > BigInt(srcAmount)) { | ||
throw new Error(`ZeroX calc ${calc} > srcAmount ${srcAmount}`); | ||
} | ||
srcAmount = calc.toString(); | ||
} | ||
} | ||
const swapData = this.buildSimpleSwapData(data, srcAmount); | ||
return { | ||
needWrapNative: this.needWrapNative, | ||
dexFuncHasRecipient: false, | ||
exchangeData: swapData, | ||
targetExchange: this.getExchange(data), | ||
returnAmountPos: undefined, | ||
}; | ||
} | ||
getDirectParam(srcToken, destToken, srcAmount, destAmount, expectedAmount, data, side, permit, uuid, feePercent, deadline, partner, beneficiary, contractMethod) { | ||
@@ -190,8 +182,8 @@ const usePermit = permit !== '0x'; | ||
return this.routerInterface.encodeFunctionData(usePermit | ||
? types_1.ZeroXFunctions.swapOnZeroXv2WithPermit | ||
: types_1.ZeroXFunctions.swapOnZeroXv2, params); | ||
? ZeroXFunctions.swapOnZeroXv2WithPermit | ||
: ZeroXFunctions.swapOnZeroXv2, params); | ||
case 4: | ||
return this.routerInterface.encodeFunctionData(usePermit | ||
? types_1.ZeroXFunctions.swapOnZeroXv4WithPermit | ||
: types_1.ZeroXFunctions.swapOnZeroXv4, params); | ||
? ZeroXFunctions.swapOnZeroXv4WithPermit | ||
: ZeroXFunctions.swapOnZeroXv4, params); | ||
default: | ||
@@ -225,3 +217,3 @@ throw new Error(`ZeroX version ${data.version} is not supported!`); | ||
static getDirectFunctionName() { | ||
return [types_1.ZeroXFunctions.swapOnZeroXv2, types_1.ZeroXFunctions.swapOnZeroXv4]; | ||
return [ZeroXFunctions.swapOnZeroXv2, ZeroXFunctions.swapOnZeroXv4]; | ||
} | ||
@@ -228,0 +220,0 @@ } |
@@ -1,2 +0,1 @@ | ||
import { Address } from '@paraswap/sdk'; | ||
import { NumberAsString } from '../../types'; | ||
@@ -45,30 +44,2 @@ export declare enum OrderStatus { | ||
export declare type ZeroXSignedOrder = ZeroXSignedOrderV2 | ZeroXSignedOrderV4; | ||
export declare enum ZeroXFunctions { | ||
swapOnZeroXv2 = "swapOnZeroXv2", | ||
swapOnZeroXv4 = "swapOnZeroXv4", | ||
swapOnZeroXv2WithPermit = "swapOnZeroXv2WithPermit", | ||
swapOnZeroXv4WithPermit = "swapOnZeroXv4WithPermit" | ||
} | ||
export declare type ZeroXData = { | ||
version: number; | ||
order: ZeroXSignedOrder; | ||
}; | ||
export declare type SwapOnZeroXParam = [ | ||
srcToken: Address, | ||
destToken: Address, | ||
srcAmount: NumberAsString, | ||
destAmount: NumberAsString, | ||
exchange: Address, | ||
payload: string | ||
]; | ||
export declare type SwapOnZeroXWithPermitParam = [ | ||
srcToken: Address, | ||
destToken: Address, | ||
srcAmount: NumberAsString, | ||
destAmount: NumberAsString, | ||
exchange: Address, | ||
payload: string, | ||
permit: string | ||
]; | ||
export declare type ZeroXParam = SwapOnZeroXParam | SwapOnZeroXWithPermitParam; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ZeroXFunctions = exports.OrderStatus = void 0; | ||
exports.OrderStatus = void 0; | ||
var OrderStatus; | ||
@@ -14,9 +14,2 @@ (function (OrderStatus) { | ||
})(OrderStatus = exports.OrderStatus || (exports.OrderStatus = {})); | ||
var ZeroXFunctions; | ||
(function (ZeroXFunctions) { | ||
ZeroXFunctions["swapOnZeroXv2"] = "swapOnZeroXv2"; | ||
ZeroXFunctions["swapOnZeroXv4"] = "swapOnZeroXv4"; | ||
ZeroXFunctions["swapOnZeroXv2WithPermit"] = "swapOnZeroXv2WithPermit"; | ||
ZeroXFunctions["swapOnZeroXv4WithPermit"] = "swapOnZeroXv4WithPermit"; | ||
})(ZeroXFunctions = exports.ZeroXFunctions || (exports.ZeroXFunctions = {})); | ||
//# sourceMappingURL=types.js.map |
{ | ||
"name": "@paraswap/dex-lib", | ||
"version": "4.0.22", | ||
"version": "4.0.23", | ||
"main": "build/index.js", | ||
@@ -5,0 +5,0 @@ "types": "build/index.d.ts", |
@@ -26,6 +26,7 @@ import dotenv from 'dotenv'; | ||
nativeTokenAmount: string, | ||
slippage?: number | undefined, | ||
excludeNativeTokenTests: boolean = false, | ||
) { | ||
const config = generateConfig(network); | ||
const provider = new StaticJsonRpcProvider( | ||
generateConfig(network).privateHttpProvider, | ||
config.privateHttpProvider, | ||
network, | ||
@@ -36,2 +37,3 @@ ); | ||
const nativeTokenSymbol = NativeTokenSymbols[network]; | ||
const sleepMs = 10000; | ||
@@ -42,7 +44,7 @@ const sideToContractMethods = new Map([ | ||
[ | ||
ContractMethod.swapExactAmountIn, | ||
ContractMethod.swapExactAmountInOnBalancerV2, | ||
// ContractMethod.simpleSwap, | ||
// ContractMethod.megaSwap, | ||
// ContractMethod.multiSwap, | ||
// ContractMethod.megaSwap, | ||
ContractMethod.swapExactAmountIn, | ||
ContractMethod.swapExactAmountInOnBalancerV2, | ||
], | ||
@@ -53,7 +55,6 @@ ], | ||
[ | ||
ContractMethod.swapExactAmountOut, | ||
ContractMethod.swapExactAmountOutOnBalancerV2, | ||
// ContractMethod.simpleBuy, | ||
// ContractMethod.buy, | ||
// DirectMethodsV6.directBuy, | ||
ContractMethod.swapExactAmountOut, | ||
ContractMethod.swapExactAmountOutOnBalancerV2, | ||
], | ||
@@ -66,55 +67,115 @@ ], | ||
describe(`${side}`, () => { | ||
contractMethods.forEach((contractMethod: string) => { | ||
contractMethods.forEach((contractMethod: ContractMethod) => { | ||
describe(`${contractMethod}`, () => { | ||
it(`${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { | ||
await testE2E( | ||
tokens[nativeTokenSymbol], | ||
tokens[tokenASymbol], | ||
holders[nativeTokenSymbol], | ||
side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, | ||
side, | ||
dexKey, | ||
contractMethod as any, | ||
network, | ||
provider, | ||
undefined, | ||
undefined, | ||
undefined, | ||
slippage, | ||
); | ||
}); | ||
it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { | ||
await testE2E( | ||
tokens[tokenASymbol], | ||
tokens[nativeTokenSymbol], | ||
holders[tokenASymbol], | ||
side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, | ||
side, | ||
dexKey, | ||
contractMethod as any, | ||
network, | ||
provider, | ||
undefined, | ||
undefined, | ||
undefined, | ||
slippage, | ||
); | ||
}); | ||
it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { | ||
await testE2E( | ||
tokens[tokenASymbol], | ||
tokens[tokenBSymbol], | ||
holders[tokenASymbol], | ||
side === SwapSide.SELL ? tokenAAmount : tokenBAmount, | ||
side, | ||
dexKey, | ||
contractMethod as any, | ||
network, | ||
provider, | ||
undefined, | ||
undefined, | ||
undefined, | ||
slippage, | ||
); | ||
}); | ||
if (excludeNativeTokenTests) { | ||
it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { | ||
await testE2E( | ||
tokens[tokenASymbol], | ||
tokens[tokenBSymbol], | ||
holders[tokenASymbol], | ||
side === SwapSide.SELL ? tokenAAmount : tokenBAmount, | ||
side, | ||
dexKey, | ||
contractMethod, | ||
network, | ||
provider, | ||
undefined, | ||
undefined, | ||
undefined, | ||
undefined, | ||
sleepMs, | ||
); | ||
}); | ||
it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => { | ||
await testE2E( | ||
tokens[tokenBSymbol], | ||
tokens[tokenASymbol], | ||
holders[tokenBSymbol], | ||
side === SwapSide.SELL ? tokenBAmount : tokenAAmount, | ||
side, | ||
dexKey, | ||
contractMethod, | ||
network, | ||
provider, | ||
undefined, | ||
undefined, | ||
undefined, | ||
undefined, | ||
sleepMs, | ||
); | ||
}); | ||
} else { | ||
it(`${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { | ||
await testE2E( | ||
tokens[nativeTokenSymbol], | ||
tokens[tokenASymbol], | ||
holders[nativeTokenSymbol], | ||
side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, | ||
side, | ||
dexKey, | ||
contractMethod, | ||
network, | ||
provider, | ||
undefined, | ||
undefined, | ||
undefined, | ||
undefined, | ||
sleepMs, | ||
); | ||
}); | ||
it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { | ||
await testE2E( | ||
tokens[tokenASymbol], | ||
tokens[nativeTokenSymbol], | ||
holders[tokenASymbol], | ||
side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, | ||
side, | ||
dexKey, | ||
contractMethod, | ||
network, | ||
provider, | ||
undefined, | ||
undefined, | ||
undefined, | ||
undefined, | ||
sleepMs, | ||
); | ||
}); | ||
it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { | ||
await testE2E( | ||
tokens[tokenASymbol], | ||
tokens[tokenBSymbol], | ||
holders[tokenASymbol], | ||
side === SwapSide.SELL ? tokenAAmount : tokenBAmount, | ||
side, | ||
dexKey, | ||
contractMethod, | ||
network, | ||
provider, | ||
undefined, | ||
undefined, | ||
undefined, | ||
undefined, | ||
sleepMs, | ||
); | ||
}); | ||
it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => { | ||
await testE2E( | ||
tokens[tokenBSymbol], | ||
tokens[tokenASymbol], | ||
holders[tokenBSymbol], | ||
side === SwapSide.SELL ? tokenBAmount : tokenAAmount, | ||
side, | ||
dexKey, | ||
contractMethod, | ||
network, | ||
provider, | ||
undefined, | ||
undefined, | ||
undefined, | ||
undefined, | ||
sleepMs, | ||
); | ||
}); | ||
} | ||
}); | ||
@@ -128,3 +189,3 @@ }); | ||
describe('BalancerV2 E2E', () => { | ||
describe('BalancerV2 MAINNET', () => { | ||
describe('Mainnet', () => { | ||
const dexKey = 'BalancerV2'; | ||
@@ -139,3 +200,3 @@ const network = Network.MAINNET; | ||
describe.only('GHO -> USDT', () => { | ||
describe('GHO -> USDT', () => { | ||
const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = | ||
@@ -806,3 +867,3 @@ [ | ||
describe('BalancerV2 Polygon_V6', () => { | ||
describe('Polygon_v6', () => { | ||
const dexKey = 'BalancerV2'; | ||
@@ -920,3 +981,3 @@ const network = Network.POLYGON; | ||
describe('BalancerV2 ARBITRUM', () => { | ||
describe('Arbitrum', () => { | ||
const dexKey = 'BalancerV2'; | ||
@@ -1099,3 +1160,3 @@ const network = Network.ARBITRUM; | ||
describe('BeetsFi FANTOM', () => { | ||
describe('Fantom', () => { | ||
const dexKey = 'BeetsFi'; | ||
@@ -1221,3 +1282,3 @@ const network = Network.FANTOM; | ||
describe('BalancerV2 Polygon', () => { | ||
describe('Polygon', () => { | ||
const dexKey = 'BalancerV2'; | ||
@@ -1316,3 +1377,3 @@ const network = Network.POLYGON; | ||
describe('BalancerV2 Avalanche', () => { | ||
describe('Avalanche', () => { | ||
const dexKey = 'BalancerV2'; | ||
@@ -1493,47 +1554,49 @@ const network = Network.AVALANCHE; | ||
describe('BalancerV2 Base', () => { | ||
describe('Base', () => { | ||
const dexKey = 'BalancerV2'; | ||
const network = Network.BASE; | ||
const tokenASymbol: string = 'USDC'; | ||
const tokenBSymbol: string = 'GOLD'; | ||
describe('USDC -> GOLD', () => { | ||
const tokenASymbol: string = 'USDC'; | ||
const tokenBSymbol: string = 'GOLD'; | ||
const tokenAAmount: string = '11110010'; | ||
const tokenBAmount: string = '210000000000000000000'; | ||
const nativeTokenAmount = '1000000000000000000'; | ||
const tokenAAmount: string = '11110010'; | ||
const tokenBAmount: string = '210000000000000000000'; | ||
const nativeTokenAmount = '1000000000000000000'; | ||
testForNetwork( | ||
network, | ||
dexKey, | ||
tokenASymbol, | ||
tokenBSymbol, | ||
tokenAAmount, | ||
tokenBAmount, | ||
nativeTokenAmount, | ||
); | ||
}); | ||
testForNetwork( | ||
network, | ||
dexKey, | ||
tokenASymbol, | ||
tokenBSymbol, | ||
tokenAAmount, | ||
tokenBAmount, | ||
nativeTokenAmount, | ||
); | ||
}); | ||
describe('BalancerV2_MAINNET', () => { | ||
const dexKey = 'BalancerV2'; | ||
const network = Network.MAINNET; | ||
describe('WETH -> USDC', () => { | ||
const tokenASymbol: string = 'WETH'; | ||
const tokenBSymbol: string = 'USDC'; | ||
const tokenASymbol: string = 'USDC'; | ||
const tokenBSymbol: string = 'USDT'; | ||
// const tokenAAmount: string = '375699066125449'; | ||
const tokenAAmount: string = '300000000000000'; | ||
// const tokenBAmount: string = '1196427'; | ||
const tokenBAmount: string = '1000000'; | ||
const nativeTokenAmount = '1000000000000000000'; | ||
const tokenAAmount: string = '11110010'; | ||
const tokenBAmount: string = '21000000'; | ||
const nativeTokenAmount = '1000000000000000000'; | ||
testForNetwork( | ||
network, | ||
dexKey, | ||
tokenASymbol, | ||
tokenBSymbol, | ||
tokenAAmount, | ||
tokenBAmount, | ||
nativeTokenAmount, | ||
); | ||
testForNetwork( | ||
network, | ||
dexKey, | ||
tokenASymbol, | ||
tokenBSymbol, | ||
tokenAAmount, | ||
tokenBAmount, | ||
nativeTokenAmount, | ||
true, | ||
); | ||
}); | ||
}); | ||
describe('BalancerV2_GNOSIS', () => { | ||
describe('Gnosis', () => { | ||
const dexKey = 'BalancerV2'; | ||
@@ -1540,0 +1603,0 @@ const network = Network.GNOSIS; |
@@ -33,7 +33,5 @@ /* eslint-disable no-console */ | ||
const params = balancerV2.getBalancerParam( | ||
const params = balancerV2.getBalancerV2BatchSwapParam( | ||
srcTokenAddress, | ||
destTokenAddress, | ||
'0', | ||
'0', | ||
{ | ||
@@ -48,2 +46,4 @@ swaps: [ | ||
side, | ||
balancerV2.dexHelper.config.data.augustusV6Address!, | ||
balancerV2.dexHelper.config.data.augustusV6Address!, | ||
); | ||
@@ -616,81 +616,239 @@ | ||
describe('GyroE', () => { | ||
// sDAI<>GYD - more likely to have continued liqudity | ||
const gyroEAddr = '0x1cce5169bde03f3d5ad0206f6bd057953539dae6'; | ||
describe('sDAI > GYD', () => { | ||
// sDAI<>GYD - more likely to have continued liqudity | ||
const gyroEAddr = '0x1cce5169bde03f3d5ad0206f6bd057953539dae6'; | ||
it('getPoolIdentifiers and getPricesVolume', async function () { | ||
const network = Network.MAINNET; | ||
const dexHelper = new DummyDexHelper(network); | ||
// const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); | ||
const blocknumber = 19425305; | ||
const balancerV2 = new BalancerV2(network, dexKey, dexHelper); | ||
const tokens = Tokens[network]; | ||
it('getPoolIdentifiers and getPricesVolume', async function () { | ||
const network = Network.MAINNET; | ||
const dexHelper = new DummyDexHelper(network); | ||
// const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); | ||
const blocknumber = 19425305; | ||
const balancerV2 = new BalancerV2(network, dexKey, dexHelper); | ||
const tokens = Tokens[network]; | ||
await balancerV2.initializePricing(blocknumber); | ||
await balancerV2.initializePricing(blocknumber); | ||
const pools = await balancerV2.getPoolIdentifiers( | ||
tokens.GYD, | ||
tokens.sDAI, | ||
SwapSide.SELL, | ||
blocknumber, | ||
); | ||
console.log('GYD <> sDAI Pool Identifiers (Mainnet): ', pools); | ||
const pools = await balancerV2.getPoolIdentifiers( | ||
tokens.GYD, | ||
tokens.sDAI, | ||
SwapSide.SELL, | ||
blocknumber, | ||
); | ||
console.log('GYD <> sDAI Pool Identifiers (Mainnet): ', pools); | ||
const isPool = pools.find(poolIdentifier => | ||
poolIdentifier.includes(gyroEAddr), | ||
); | ||
const isPool = pools.find(poolIdentifier => | ||
poolIdentifier.includes(gyroEAddr), | ||
); | ||
expect(isPool).toBeDefined(); | ||
expect(isPool).toBeDefined(); | ||
const poolPrices = await balancerV2.getPricesVolume( | ||
tokens.GYD, | ||
tokens.sDAI, | ||
amounts, | ||
SwapSide.SELL, | ||
blocknumber, | ||
pools, | ||
); | ||
console.log('GYD <> sDAI Pool Prices (Mainnet): ', poolPrices); | ||
const poolPrices = await balancerV2.getPricesVolume( | ||
tokens.GYD, | ||
tokens.sDAI, | ||
amounts, | ||
SwapSide.SELL, | ||
blocknumber, | ||
pools, | ||
); | ||
console.log('GYD <> sDAI Pool Prices (Mainnet): ', poolPrices); | ||
expect(poolPrices).not.toBeNull(); | ||
checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); | ||
const isPoolPrice = poolPrices!.find(price => | ||
price.data.poolId.includes(gyroEAddr), | ||
); | ||
expect(isPoolPrice).toBeDefined(); | ||
expect(poolPrices).not.toBeNull(); | ||
checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); | ||
const isPoolPrice = poolPrices!.find(price => | ||
price.data.poolId.includes(gyroEAddr), | ||
); | ||
expect(isPoolPrice).toBeDefined(); | ||
const onChainPrices = await getOnChainPricingForWeightedPool( | ||
balancerV2, | ||
blocknumber, | ||
isPoolPrice!, | ||
amounts, | ||
tokens.GYD.address, | ||
tokens.sDAI.address, | ||
SwapSide.SELL, | ||
); | ||
const onChainPrices = await getOnChainPricingForWeightedPool( | ||
balancerV2, | ||
blocknumber, | ||
isPoolPrice!, | ||
amounts, | ||
tokens.GYD.address, | ||
tokens.sDAI.address, | ||
SwapSide.SELL, | ||
); | ||
console.log('GYD <> sDAI on-chain prices: ', onChainPrices); | ||
console.log('GYD <> sDAI on-chain prices: ', onChainPrices); | ||
expect(onChainPrices).toEqual(isPoolPrice!.prices); | ||
expect(onChainPrices).toEqual(isPoolPrice!.prices); | ||
await balancerV2.releaseResources(); | ||
await balancerV2.releaseResources(); | ||
}); | ||
it('getTopPoolsForToken', async function () { | ||
const network = Network.MAINNET; | ||
const dexHelper = new DummyDexHelper(network); | ||
const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); | ||
const balancerV2 = new BalancerV2(network, dexKey, dexHelper); | ||
await balancerV2.initializePricing(blocknumber); | ||
const tokens = Tokens[network]; | ||
const poolLiquidity = await balancerV2.getTopPoolsForToken( | ||
tokens.sDAI.address.toLowerCase(), | ||
10, | ||
); | ||
console.log('sDAI Top Pools (Mainnet):', poolLiquidity); | ||
checkPoolsLiquidity(poolLiquidity, tokens.sDAI.address, dexKey); | ||
const isTopPool = poolLiquidity.find( | ||
pool => pool.address === gyroEAddr, | ||
); | ||
expect(isTopPool).toBeDefined(); | ||
await balancerV2.releaseResources(); | ||
}); | ||
}); | ||
it('getTopPoolsForToken', async function () { | ||
const network = Network.MAINNET; | ||
const dexHelper = new DummyDexHelper(network); | ||
const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); | ||
const balancerV2 = new BalancerV2(network, dexKey, dexHelper); | ||
await balancerV2.initializePricing(blocknumber); | ||
const tokens = Tokens[network]; | ||
describe('WETH / USDC', () => { | ||
const gyroEAddr = '0x4c42b5057a8663e2b1ac21685d1502c937a03817'; | ||
const poolLiquidity = await balancerV2.getTopPoolsForToken( | ||
tokens.sDAI.address.toLowerCase(), | ||
10, | ||
); | ||
console.log('sDAI Top Pools (Mainnet):', poolLiquidity); | ||
it('SELL WETH -> USDC getPoolIdentifiers and getPricesVolume', async function () { | ||
const network = Network.BASE; | ||
checkPoolsLiquidity(poolLiquidity, tokens.sDAI.address, dexKey); | ||
const isTopPool = poolLiquidity.find(pool => pool.address === gyroEAddr); | ||
expect(isTopPool).toBeDefined(); | ||
await balancerV2.releaseResources(); | ||
const dexHelper = new DummyDexHelper(network); | ||
const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); | ||
// const blocknumber = 19425305; | ||
const balancerV2 = new BalancerV2(network, dexKey, dexHelper); | ||
const tokens = Tokens[network]; | ||
const amounts = [ | ||
0n, | ||
BI_POWS[18], | ||
2n * BI_POWS[18], | ||
3n * BI_POWS[18], | ||
4n * BI_POWS[18], | ||
5n * BI_POWS[18], | ||
6n * BI_POWS[18], | ||
7n * BI_POWS[18], | ||
8n * BI_POWS[18], | ||
9n * BI_POWS[18], | ||
10n * BI_POWS[18], | ||
]; | ||
await balancerV2.initializePricing(blocknumber); | ||
const pools = await balancerV2.getPoolIdentifiers( | ||
tokens.WETH, | ||
tokens.USDC, | ||
SwapSide.SELL, | ||
blocknumber, | ||
); | ||
console.log('WETH <> USDC Pool Identifiers (Mainnet): ', pools); | ||
const isPool = pools.find(poolIdentifier => | ||
poolIdentifier.includes(gyroEAddr), | ||
); | ||
expect(isPool).toBeDefined(); | ||
const poolPrices = await balancerV2.getPricesVolume( | ||
tokens.WETH, | ||
tokens.USDC, | ||
amounts, | ||
SwapSide.SELL, | ||
blocknumber, | ||
pools, | ||
); | ||
console.log('WETH <> USDC Pool Prices (Base): ', poolPrices); | ||
expect(poolPrices).not.toBeNull(); | ||
// checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); | ||
const isPoolPrice = poolPrices!.find(price => | ||
price.data.poolId.includes(gyroEAddr), | ||
); | ||
expect(isPoolPrice).toBeDefined(); | ||
const onChainPrices = await getOnChainPricingForWeightedPool( | ||
balancerV2, | ||
blocknumber, | ||
isPoolPrice!, | ||
amounts, | ||
tokens.WETH.address, | ||
tokens.USDC.address, | ||
SwapSide.SELL, | ||
); | ||
console.log('WETH <> USDC on-chain prices: ', onChainPrices); | ||
expect(onChainPrices).toEqual(isPoolPrice!.prices); | ||
await balancerV2.releaseResources(); | ||
}); | ||
it('SELL USDC -> WETH getPoolIdentifiers and getPricesVolume', async function () { | ||
const network = Network.BASE; | ||
const dexHelper = new DummyDexHelper(network); | ||
// const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); | ||
const blocknumber = 24931862; | ||
const balancerV2 = new BalancerV2(network, dexKey, dexHelper); | ||
const tokens = Tokens[network]; | ||
const amounts = [ | ||
0n, | ||
1000000n, | ||
// BI_POWS[6], | ||
// 2n * BI_POWS[6], | ||
// 3n * BI_POWS[6], | ||
// 4n * BI_POWS[6], | ||
// 5n * BI_POWS[6], | ||
// 6n * BI_POWS[6], | ||
// 7n * BI_POWS[6], | ||
// 8n * BI_POWS[6], | ||
// 9n * BI_POWS[6], | ||
// 10n * BI_POWS[6], | ||
]; | ||
await balancerV2.initializePricing(blocknumber); | ||
const pools = await balancerV2.getPoolIdentifiers( | ||
tokens.USDC, | ||
tokens.WETH, | ||
SwapSide.SELL, | ||
blocknumber, | ||
); | ||
console.log('USDC -> WETH Pool Identifiers (Base): ', pools); | ||
const isPool = pools.find(poolIdentifier => | ||
poolIdentifier.includes(gyroEAddr), | ||
); | ||
expect(isPool).toBeDefined(); | ||
const poolPrices = await balancerV2.getPricesVolume( | ||
tokens.USDC, | ||
tokens.WETH, | ||
amounts, | ||
SwapSide.SELL, | ||
blocknumber, | ||
pools, | ||
); | ||
console.log('USDC -> WETH Pool Prices (Base): ', poolPrices); | ||
expect(poolPrices).not.toBeNull(); | ||
// checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); | ||
const isPoolPrice = poolPrices!.find(price => | ||
price.data.poolId.includes(gyroEAddr), | ||
); | ||
expect(isPoolPrice).toBeDefined(); | ||
console.log('isPoolPrice: ', isPoolPrice); | ||
const onChainPrices = await getOnChainPricingForWeightedPool( | ||
balancerV2, | ||
blocknumber, | ||
isPoolPrice!, | ||
amounts, | ||
tokens.USDC.address, | ||
tokens.WETH.address, | ||
SwapSide.SELL, | ||
); | ||
console.log('USDC -> WETH on-chain prices: ', onChainPrices); | ||
expect(onChainPrices).toEqual(isPoolPrice!.prices); | ||
await balancerV2.releaseResources(); | ||
}); | ||
}); | ||
@@ -697,0 +855,0 @@ }); |
@@ -24,4 +24,3 @@ import { DexParams } from './types'; | ||
[Network.BASE]: { | ||
subgraphURL: | ||
'https://api.studio.thegraph.com/query/24660/balancer-base-v2/version/latest', | ||
subgraphURL: 'E7XyutxXVLrp8njmjF16Hh38PCJuHm12RRyMt5ma4ctX', | ||
vaultAddress: '0xBA12222222228d8Ba445958a75a0704d566BF2C8', | ||
@@ -28,0 +27,0 @@ }, |
@@ -11,5 +11,5 @@ import { Network, SwapSide } from '../../constants'; | ||
} = { | ||
[Network.ARBITRUM]: [ | ||
[Network.MAINNET]: [ | ||
{ | ||
srcToken: 'WETH', | ||
srcToken: 'USDT', | ||
destToken: 'USDC', | ||
@@ -21,3 +21,3 @@ amount: '10000', | ||
srcToken: 'USDC', | ||
destToken: 'WETH', | ||
destToken: 'USDT', | ||
amount: '10000', | ||
@@ -24,0 +24,0 @@ swapSide: SwapSide.SELL, |
@@ -118,4 +118,4 @@ import dotenv from 'dotenv'; | ||
} | ||
srcToken = smartTokens[testCase.srcToken]; | ||
destToken = smartTokens[testCase.destToken]; | ||
srcToken = new SmartToken(tokens[testCase.srcToken]); | ||
destToken = new SmartToken(tokens[testCase.destToken]); | ||
@@ -122,0 +122,0 @@ srcToken.addBalance(testAccount.address, MAX_UINT); |
@@ -17,4 +17,3 @@ import { DexParams } from './types'; | ||
[Network.BASE]: { | ||
subgraphURL: | ||
'https://api.studio.thegraph.com/query/42519/maverick-base/version/latest', | ||
subgraphURL: 'CSxkHjxpG1TxTBQMn55uG1DWpdD4Lsix4RNX4RTLvK4T', | ||
routerAddress: '0x32AED3Bce901DA12ca8489788F3A99fCe1056e14', | ||
@@ -21,0 +20,0 @@ poolInspectorAddress: '0x65A3AD03Be97619284bA7AA1E3Ca05638B9d6364', |
@@ -120,4 +120,3 @@ import { DexParams } from './types'; | ||
initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, | ||
subgraphURL: | ||
'https://api.studio.thegraph.com/query/48211/uniswap-v3-base/version/latest', | ||
subgraphURL: 'GqzP4Xaehti8KSfQmv3ZctFSjnSUYZ4En5NRsiTbvZpz', | ||
}, | ||
@@ -124,0 +123,0 @@ }, |
@@ -8,5 +8,3 @@ import { Address, Token } from '../src/types'; | ||
export type StateSimulateApiOverride = { | ||
storage: { | ||
value: Record<string, string>; | ||
}; | ||
storage: Record<string, string>; | ||
}; | ||
@@ -13,0 +11,0 @@ |
/* eslint-disable no-console */ | ||
import axios from 'axios'; | ||
import { Address } from '@paraswap/core'; | ||
import { TxObject } from '../src/types'; | ||
import { StateOverrides, StateSimulateApiOverride } from './smart-tokens'; | ||
import { StaticJsonRpcProvider, Provider } from '@ethersproject/providers'; | ||
import Web3 from 'web3'; | ||
import { Provider, StaticJsonRpcProvider } from '@ethersproject/providers'; | ||
import { ethers } from 'ethers'; | ||
import { Network } from '../build/constants'; | ||
import { Address } from '@paraswap/core'; | ||
@@ -12,5 +13,3 @@ const TENDERLY_TOKEN = process.env.TENDERLY_TOKEN; | ||
const TENDERLY_PROJECT = process.env.TENDERLY_PROJECT; | ||
const TENDERLY_FORK_ID = process.env.TENDERLY_FORK_ID; | ||
const TENDERLY_TEST_NET_RPC = process.env.TENDERLY_TEST_NET_RPC; | ||
const TENDERLY_FORK_LAST_TX_ID = process.env.TENDERLY_FORK_LAST_TX_ID; | ||
const TENDERLY_VNET_ID = process.env.TENDERLY_VNET_ID; | ||
@@ -25,5 +24,7 @@ export type SimulationResult = { | ||
export interface TransactionSimulator { | ||
forkId: string; | ||
vnetId: string; | ||
setup(): Promise<void>; | ||
getChainNameByChainId(network: number): string; | ||
simulate( | ||
@@ -36,3 +37,3 @@ params: TxObject, | ||
export class EstimateGasSimulation implements TransactionSimulator { | ||
forkId: string = '0'; | ||
vnetId: string = '0'; | ||
@@ -43,2 +44,6 @@ constructor(private provider: Provider) {} | ||
getChainNameByChainId(network: number) { | ||
return ''; | ||
} | ||
async simulate( | ||
@@ -64,20 +69,25 @@ params: TxObject, | ||
export class TenderlySimulation implements TransactionSimulator { | ||
testNetRPC: StaticJsonRpcProvider | null = null; | ||
lastTx: string = ''; | ||
forkId: string = ''; | ||
vnetId: string = ''; | ||
rpcURL: string = ''; | ||
maxGasLimit = 80000000; | ||
constructor( | ||
private network: Number = 1, | ||
forkId?: string, | ||
lastTransactionId?: string, | ||
) { | ||
if (forkId && lastTransactionId) { | ||
this.forkId = forkId; | ||
this.lastTx = lastTransactionId; | ||
} | ||
private readonly chainIdToChainNameMap: { [key: number]: string } = { | ||
[Network.MAINNET]: 'mainnet', | ||
[Network.BSC]: 'bnb', | ||
[Network.POLYGON]: 'polygon', | ||
[Network.AVALANCHE]: 'avalanche-mainnet', | ||
[Network.FANTOM]: 'fantom', | ||
[Network.ARBITRUM]: 'arbitrum', | ||
[Network.OPTIMISM]: 'optimistic', | ||
[Network.GNOSIS]: 'gnosis-chain', | ||
[Network.BASE]: 'base', | ||
}; | ||
constructor(private network: number = 1) {} | ||
getChainNameByChainId(network: number): string { | ||
return this.chainIdToChainNameMap[network]; | ||
} | ||
async setup() { | ||
// Fork the mainnet | ||
if (!TENDERLY_TOKEN) | ||
@@ -88,13 +98,34 @@ throw new Error( | ||
if (this.forkId && this.lastTx) return; | ||
const findAdminRPC = (rpcs: { name: string; url: string }[]) => { | ||
return rpcs.find( | ||
rpc => rpc.name.toLowerCase() === 'Admin RPC'.toLowerCase(), | ||
); | ||
}; | ||
if (TENDERLY_FORK_ID) { | ||
if (!TENDERLY_FORK_LAST_TX_ID) throw new Error('Always set last tx id'); | ||
this.forkId = TENDERLY_FORK_ID; | ||
this.lastTx = TENDERLY_FORK_LAST_TX_ID; | ||
return; | ||
} | ||
if (TENDERLY_VNET_ID) { | ||
this.vnetId = TENDERLY_VNET_ID; | ||
if (TENDERLY_TEST_NET_RPC) { | ||
this.testNetRPC = new StaticJsonRpcProvider(TENDERLY_TEST_NET_RPC); | ||
try { | ||
let res = await axios.get( | ||
`https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/vnets/${this.vnetId}`, | ||
{ | ||
timeout: 200000, | ||
headers: { | ||
'x-access-key': TENDERLY_TOKEN, | ||
}, | ||
}, | ||
); | ||
const rpc = findAdminRPC(res.data.rpcs); | ||
if (!rpc) { | ||
throw new Error(`RPC url was not found for testnet: ${this.vnetId}`); | ||
} | ||
this.rpcURL = rpc.url; | ||
} catch (e) { | ||
console.error(`TenderlySimulation_setup:`, e); | ||
throw e; | ||
} | ||
return; | ||
@@ -106,8 +137,23 @@ } | ||
let res = await axios.post( | ||
`https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/fork`, | ||
`https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/vnets`, | ||
{ | ||
network_id: this.network.toString(), | ||
slug: `e2e-tests-testnetwork-${this.network.toString()}-${Date.now()}`, | ||
fork_config: { | ||
network_id: this.network, | ||
}, | ||
virtual_network_config: { | ||
chain_config: { | ||
chain_id: this.network, | ||
}, | ||
}, | ||
sync_state_config: { | ||
enabled: false, | ||
}, | ||
explorer_page_config: { | ||
enabled: true, | ||
verification_visibility: 'bytecode', | ||
}, | ||
}, | ||
{ | ||
timeout: 20000, | ||
timeout: 200000, | ||
headers: { | ||
@@ -118,4 +164,10 @@ 'x-access-key': TENDERLY_TOKEN, | ||
); | ||
this.forkId = res.data.simulation_fork.id; | ||
this.lastTx = res.data.root_transaction.id; | ||
this.vnetId = res.data.id; | ||
const rpc = findAdminRPC(res.data.rpcs); | ||
if (!rpc) { | ||
throw new Error(`RPC url was not found for testnet: ${this.vnetId}`); | ||
} | ||
this.rpcURL = rpc.url; | ||
} catch (e) { | ||
@@ -128,14 +180,4 @@ console.error(`TenderlySimulation_setup:`, e); | ||
async simulate(params: TxObject, stateOverrides?: StateOverrides) { | ||
let _params = { | ||
from: params.from, | ||
to: params.to, | ||
save: true, | ||
root: this.lastTx, | ||
value: params.value || '0', | ||
gas: this.maxGasLimit, | ||
input: params.data, | ||
state_objects: {}, | ||
}; | ||
try { | ||
if (this.testNetRPC) return this.executeTransactionOnTestnet(params); | ||
let stateOverridesParams = {}; | ||
@@ -145,4 +187,3 @@ if (stateOverrides) { | ||
const result = await axios.post( | ||
` | ||
https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/contracts/encode-states`, | ||
`https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/contracts/encode-states`, | ||
stateOverrides, | ||
@@ -156,3 +197,3 @@ { | ||
_params.state_objects = Object.keys(result.data.stateOverrides).reduce( | ||
stateOverridesParams = Object.keys(result.data.stateOverrides).reduce( | ||
(acc, contract) => { | ||
@@ -168,2 +209,4 @@ const _storage = result.data.stateOverrides[contract].value; | ||
); | ||
await this.executeStateOverrides(stateOverridesParams); | ||
} | ||
@@ -173,5 +216,21 @@ | ||
const { data } = await axios.post( | ||
`https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/fork/${this.forkId}/simulate`, | ||
_params, | ||
`https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/vnets/${this.vnetId}/transactions`, | ||
{ | ||
callArgs: { | ||
from: params.from, | ||
to: params.to, | ||
value: | ||
params.value === '0' | ||
? '0x0' | ||
: ethers.utils.hexStripZeros( | ||
ethers.utils.hexlify(BigInt(params.value)), | ||
), | ||
gas: ethers.utils.hexStripZeros( | ||
ethers.utils.hexlify(BigInt(this.maxGasLimit)), | ||
), | ||
data: params.data, | ||
}, | ||
blockNumber: 'pending', | ||
}, | ||
{ | ||
timeout: 30 * 1000, | ||
@@ -184,10 +243,10 @@ headers: { | ||
const lastTx = data.simulation.id; | ||
if (data.transaction.status) { | ||
this.lastTx = lastTx; | ||
if (data.status === 'success') { | ||
return { | ||
success: true, | ||
gasUsed: data.transaction.gas_used, | ||
url: `https://dashboard.tenderly.co/${TENDERLY_ACCOUNT_ID}/${TENDERLY_PROJECT}/fork/${this.forkId}/simulation/${lastTx}`, | ||
transaction: data.transaction, | ||
gasUsed: data.gasUsed, | ||
url: `https://dashboard.tenderly.co/${TENDERLY_ACCOUNT_ID}/${TENDERLY_PROJECT}/testnet/${ | ||
this.vnetId | ||
}/tx/${this.chainIdToChainNameMap[this.network]}/${data.id}`, | ||
transaction: data.input, | ||
}; | ||
@@ -197,4 +256,6 @@ } else { | ||
success: false, | ||
url: `https://dashboard.tenderly.co/${TENDERLY_ACCOUNT_ID}/${TENDERLY_PROJECT}/fork/${this.forkId}/simulation/${lastTx}`, | ||
error: `Simulation failed: ${data.transaction.error_info.error_message} at ${data.transaction.error_info.address}`, | ||
url: `https://dashboard.tenderly.co/${TENDERLY_ACCOUNT_ID}/${TENDERLY_PROJECT}/testnet/${ | ||
this.vnetId | ||
}/tx/${this.chainIdToChainNameMap[this.network]}/${data.id}`, | ||
error: `Simulation failed ${data.error_reason}`, | ||
}; | ||
@@ -209,29 +270,33 @@ } | ||
async executeTransactionOnTestnet(params: TxObject) { | ||
const txParams = { | ||
from: params.from, | ||
to: params.to, | ||
value: Web3.utils.toHex(params.value || '0'), | ||
data: params.data, | ||
gas: '0x4c4b40', // 5,000,000 | ||
gasPrice: '0x0', // 0 | ||
}; | ||
const txHash = await this.testNetRPC!.send('eth_sendTransaction', [ | ||
txParams, | ||
]); | ||
const transaction = await this.testNetRPC!.waitForTransaction(txHash); | ||
if (transaction.status) { | ||
return { | ||
success: true, | ||
url: txHash, | ||
gasUsed: transaction.gasUsed.toString(), | ||
transaction, | ||
}; | ||
} else { | ||
return { | ||
success: false, | ||
error: `Transaction on testnet failed, hash: ${txHash}`, | ||
}; | ||
async executeStateOverrides( | ||
stateOverridesParams: Record<string, StateSimulateApiOverride>, | ||
) { | ||
if (!this.rpcURL) { | ||
throw new Error( | ||
`rpcURL is not defined for testnet: ${this.vnetId} (https://dashboard.tenderly.co/${TENDERLY_ACCOUNT_ID}/${TENDERLY_PROJECT}/testnet/${this.vnetId}`, | ||
); | ||
} | ||
const testNetRPC = new StaticJsonRpcProvider(this.rpcURL); | ||
await Promise.all( | ||
Object.keys(stateOverridesParams).map(async addr => { | ||
const storage = stateOverridesParams[addr].storage; | ||
await Promise.all( | ||
Object.keys(storage).map(async slot => { | ||
const txHash = await testNetRPC!.send('tenderly_setStorageAt', [ | ||
addr, | ||
slot, | ||
storage[slot], | ||
]); | ||
const transaction = await testNetRPC!.waitForTransaction(txHash); | ||
if (!transaction.status) { | ||
console.log(`Transaction failed: ${txHash}`); | ||
} | ||
}), | ||
); | ||
}), | ||
); | ||
} | ||
} |
@@ -449,3 +449,3 @@ import dotenv from 'dotenv'; | ||
contractAddress, | ||
ts.forkId, | ||
ts.vnetId, | ||
testContractName || '', | ||
@@ -490,3 +490,5 @@ testContractRelativePath || '', | ||
paraswap.dexHelper?.replaceProviderWithRPC( | ||
`https://rpc.tenderly.co/fork/${ts.forkId}`, | ||
`https://virtual.${ts.getChainNameByChainId(network)}.rpc.tenderly.co/${ | ||
ts.vnetId | ||
}`, | ||
); | ||
@@ -577,2 +579,3 @@ } | ||
const swapTx = await ts.simulate(swapParams); | ||
// Only log gas estimate if testing against API | ||
@@ -579,0 +582,0 @@ if (useAPI) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
22949708
3377
657513
59